====== 4.4 View-Patterns — UX-Architektur ====== //Stand: 2026-03-06// Übergeordnet: [[de:int:wvdsshell:notes:04-vsix:start|VSIX-Module — Gesamtübersicht]] Verwandt: [[de:int:wvdsshell:notes:04-vsix:amed-cafm|4.1 CAFM-Extension]] | [[de:int:wvdsshell:notes:04-vsix:amed-pims|4.2 PIMS-Extension]] | [[de:int:wvdsshell:notes:04-vsix:screen-map|4.3 Wo finde ich jetzt...?]] ===== Leitprinzip ===== Die AMED-Oberfläche ist **aufgabenorientiert**, nicht formularorientiert. Der Benutzer folgt seinem Arbeitsvorgang — die Navigation bildet den Prozess ab, nicht die Datenbankstruktur. Jede View unterstützt einen konkreten Arbeitsschritt; Referenzsprünge (z.B. Apparat → Motor → KV) sind nahtlos möglich, ohne den Kontext zu verlieren. ===== Leading Pattern: Master–Detail–Flyout ===== Das dominierende Layoutmuster (≈ 75% aller Views) besteht aus drei Zonen: ┌─────────────────────────────────────────────────────────────────┐ │ Activity Bar │ Sidebar (TreeView) │ │ │ └── amedCafmExplorer / amedPimsExplorer │ ├───────────────┼──────────────────────────────────────────────────┤ │ │ │ │ │ ┌──────────────────┬───────────────────────┐ │ │ │ │ │ DETAIL (rechts) │ │ │ │ │ MASTER │ │ │ │ │ │ (links) │ TWvdSVerticalGrid │ │ │ │ │ │ (Property-Grid) │ │ │ │ │ TWvdSGridControl│ │ │ │ │ │ — oder — ├───────────────────────┤ │ │ │ │ TWvdSTreeList │ REFERENZ-TABS │ │ │ │ │ │ ┌─────────┬─────────┐│ │ │ │ │ │ │ Tab 1 │ Tab 2 ││ │ │ │ │ │ │ Grid │ TreeList ││ │ │ │ │ │ │(Motoren)│(Prüfung)││ │ │ │ │ │ └─────────┴─────────┘│ │ │ │ └──────────────────┴───────────────────────┘ │ │ │ │ │ │ ┌─────────────────────────────┐ │ │ │ │ FLYOUT-DRAWER │ │ │ │ │ (gleitet von rechts rein) │ │ │ │ │ Feinabstimmung / Zuordnung │ │ │ │ └─────────────────────────────┘ │ │ │ │ └───────────────┴───────────────────────────────────────────────────┘ ==== Zone 1: Master (links) ==== ^ Kontrolltyp ^ Wann ^ Beispiele ^ | ''TWvdSGridControl'' | Flache Daten, hohe Zeilenanzahl, Filter/Suche | Objects, InspTasks, WorkOrders, FaultReports | | ''TWvdSTreeList'' | Hierarchische Daten, Baumnavigation | TechPlace (Anlage>Zweig>Ort), EMR (KV>Feld>Abgang), InspPlan (Regelbaum) | Verbindung zum Detail: ''OnFocusedRecordChanged'' (Grid) bzw. ''OnFocusedNodeChanged'' (TreeList) aktualisiert die rechte Seite. ==== Zone 2: Detail (rechts) ==== Die Detail-Zone besteht aus zwei vertikal gestapelten Bereichen: === 2a: Property-Grid (oben) === ^ Kontrolltyp ^ Aufgabe ^ | ''TWvdSVerticalGrid'' | Property-Grid: Schlüssel-Wert-Paare, gruppiert nach Kategorien | Kategorien entsprechen den Legacy-CategoryRows: * **Kennungen** — Item-Nr., Typ-Code, Branch * **Allgemeines** — Bezeichnung, Hersteller, Baujahr * **Technische Merkmale** — Bausteine aus ''property_schema'' (dynamisch) * **Prüfstatus** — Letzte Prüfung, Nächste Fälligkeit * **Dokumente** — Stellenblatt, Stromlaufplan, Fließbild === 2b: Referenz-Tabs (unten) === Unterhalb der VGrid zeigt ein ''TWPageControl'' **eingebettete Referenz-Grids** — read-only Übersichten gekoppelter Entitäten mit Tab-Sprung-Möglichkeit: ^ Tab-Name ^ Kontrolltyp ^ Inhalt ^ Tab-Sprung ^ | Gekoppelte Motoren | ''TWvdSGridControl'' | Motoren des aktuellen Assets (Nr, kW, KV, Status) | Doppelklick → Motors-View (vorselektiert) | | Prüfhistorie | ''TWvdSTreeList'' | Disziplin > Prüftyp > Einzelergebnis (Datum, OK/NOK)| Doppelklick → PIMS-INSP InspResult | Referenz-Tabs — Beispiel für Apparat P-4711: ┌─ Gekoppelte Motoren ─┬─ Prüfhistorie ────────────────────────────┐ │ │ │ │ Nr kW KV │ ▼ EMR │ │ M-4711-A 15 KV03 │ ▼ BGV A3 (Elektrische Sicherheit) │ │ M-4711-B 22 KV03 │ 2025-11-15 ✓ bestanden │ │ │ 2024-05-20 ✓ bestanden │ │ [Doppelklick → │ ▼ Blitzschutz │ │ Motors-View Tab] │ 2025-08-03 ✗ Mangel → Auftrag 8812 │ │ │ ▼ MECH │ │ │ ▼ Druckbehälterprüfung │ │ │ 2025-12-01 ✓ bestanden │ │ │ │ │ │ [Doppelklick → PIMS-INSP Tab] │ └───────────────────────┴────────────────────────────────────────────┘ **Prinzip:** Referenz-Tabs sind immer **read-only**. Sie beantworten die Frage "Was hängt an diesem Asset?" ohne die View zu verlassen. Die Bearbeitung (Motor ändern, Prüfung erfassen) findet immer im zuständigen Topic statt — erreichbar per Doppelklick-Sprung in einen neuen Tab. Nicht jede View hat Referenz-Tabs. Sie erscheinen nur bei Entitäten mit relevanten Querbezügen: ^ View ^ Referenz-Tabs ^ | CAFM-OBJ Detail | Gekoppelte Motoren (Grid), Prüfhistorie (TreeList) | | CAFM-EMR | Belegte Motoren (Grid) — welche Motoren hängen an diesem KV-Abgang? | | PIMS-EZA | Prüfhistorie (TreeList) — bisherige EzA-Ergebnisse dieser Anlage | | PIMS-WORK Orders | Zugehörige Meldungen (Grid) — welche Schadensmeldungen führten zum Auftrag?| ==== Zone 3: Flyout-Drawer (bei Bedarf) ==== Der Flyout-Drawer gleitet **von rechts** über das Detail-Panel und dient für: * **Feinabstimmung** — Zusatzfelder, die nicht ins Property-Grid passen (z.B. Kostendetails, Messwert-Eingabe) * **Zuordnung** — Motor einem Apparat zuweisen (Pool-Auswahl), Prüfregel zuordnen * **Schnellerfassung** — Neue Schadensmeldung, neuer Prüfauftrag ohne View-Wechsel Der Drawer schließt sich nach Bestätigung — der Master-Kontext bleibt erhalten. ===== Referenzsprung: Neuer Tab ===== Wenn das Ziel eine **eigenständige Entität** in einer anderen Extension oder einem anderen Topic ist, öffnet sich ein **neuer Tab** statt eines Drawers: Arbeitsvorgang: "Apparat prüfen, Motor-KV-Verteilung klären" Objects (Grid) ──► Apparat auswählen └─► ObjectDetail (VGrid + Referenz-Tabs) │ ├─► Tab "Gekoppelte Motoren" (read-only Grid) │ └─► Doppelklick auf Motor → NEUER TAB (Motors-View, Motor vorselektiert) │ └─► Motor-Detail → KV-Referenz → NEUER TAB (EMR-View, KV-Kontext) │ └─► Tab "Prüfhistorie" (read-only TreeList) └─► Doppelklick auf Ergebnis → NEUER TAB (PIMS-INSP InspResult) **Entscheidungsregel:** ^ Situation ^ Aktion ^ Grund ^ | Feinabstimmung / Zuordnung derselben Entität | **Flyout-Drawer** | Kontext bleibt, schnelle Rückkehr | | Referenz anzeigen (gekoppelte Entität, read-only) | **Referenz-Tab** | Übersicht ohne View-Wechsel, Doppelklick zum Springen | | Bearbeitung einer gekoppelten Entität | **Neuer Tab** | Motor, KV, Prüfung = eigenständige Entitäten mit eigener View | | Sprung in andere Extension | **Neuer Tab** | CAFM → PIMS oder PIMS → CAFM = Extension-Grenze | ===== Pattern-Zuordnung pro View ===== ==== wvds-amed-cafm ==== ^ View ^ Master (links) ^ Detail (rechts) ^ Flyout / Tab ^ | **CAFM-TP** | TWvdSTreeList (TP-Baum) | TWvdSVerticalGrid (TP-Properties) | Flyout: Standort-Details | | **CAFM-OBJ** | TWvdSGridControl (Assets) | TWvdSVerticalGrid (Asset-Props) | Flyout: Motor-Detail, Dokumente. Tab: EMR-Sprung | | **CAFM-OBJ** Detail | TWPageControl (Tabs) | TWvdSVerticalGrid (pro Tab) | Flyout: Baustein-Editor. Tab: Prüfhistorie (PIMS) | | **CAFM-EMR** | TWvdSTreeList (KV-Baum) | TWvdSGridControl (Belegung) | Flyout: Abgang-Detail, KV-Eigenschaften | ==== wvds-amed-pims ==== ^ View ^ Master (links) ^ Detail (rechts) ^ Flyout / Tab ^ | **PIMS-INSP** Plan | TWvdSTreeList (Regelbaum) | TWvdSGridControl (Aufgaben) | Flyout: Regel-Editor | | **PIMS-INSP** Tasks | TWvdSGridControl (BandedView) | — (kein inline Detail) | Tab: InspResult öffnen | | **PIMS-INSP** Result | TWvdSGridControl (Ergebnisse) | TWvdSVerticalGrid (Messwerte + Prüfung) | Flyout: Messwert-Eingabe, Checkliste | | **PIMS-EZA** | TWvdSGridControl (EzA-Liste) | TWvdSVerticalGrid (EzA-Properties) | Flyout: Sensor/Aktor-Detail, SIL-Bewertung | | **PIMS-EZA** Talk | TWvdSGridControl (Sicherheitsgespräche) | TWvdSVerticalGrid (Gesprächs-Detail) | Flyout: Begründung, Unterschriften | | **PIMS-WORK** Fault | TWvdSGridControl (Schadensmeldungen) | TWvdSVerticalGrid (Meldungs-Detail) | Flyout: Neue Meldung. Tab: Apparat-Sprung (CAFM) | | **PIMS-WORK** Orders | TWvdSGridControl (Aufträge) | TWvdSVerticalGrid (Auftrags-Detail) | Flyout: Kosten, Material. Tab: Stillstandsplanung | | **PIMS-PIPE** | TWvdSGridControl (Rohrleitungen) | TWvdSVerticalGrid ×2 (Stamm + Druckmedium) | Flyout: Eigenschafts-Editor. Tab: Prüfhistorie (INSP) | ===== Statistik ===== ^ Pattern ^ Views ^ % ^ | Grid + VGrid + Flyout | 9 | 64% | | TreeList + VGrid/Grid + Flyout | 3 | 21% | | Grid + BandedView (nur Liste) | 1 | 7% | | PageControl + VGrid (Multi-Tab) | 1 | 7% | | **Gesamt** | **14** | | ^ Interaktionsmuster ^ Views ^ Beschreibung ^ | Flyout-Drawer verfügbar | 13 | Fast jede View hat mindestens einen Flyout | | Neuer-Tab-Sprung möglich | 8 | Cross-Domain oder Cross-Topic Navigation | | Beides (Flyout + Tab) | 7 | Komplexe Views mit mehreren Arbeitsschritten | ===== Abgrenzung: Flyout vs. Drawer vs. Dialog ===== ^ Element ^ Verhalten ^ Einsatz ^ | **Flyout-Drawer** | Gleitet von rechts über Detail-Panel, schließt mit ✓/✗ | Standard für Inline-Bearbeitung | | **Modal-Dialog** | Zentriert, blockiert den Hintergrund | Bestätigungen, Lösch-Warnung, Drucken | | **Neuer Tab** | Öffnet eigenständige View in neuem Tab | Referenzsprung auf andere Entität / Domain | Der Flyout-Drawer ersetzt das Legacy-Muster "zweites VGrid unterhalb des ersten" — statt vertikalem Stapeln gibt es horizontales Einblenden. Der Vorteil: Der Master-Kontext (selektierte Zeile) bleibt sichtbar. ===== Workflow-Beispiel: Apparat → Motor → KV ===== Das Beispiel zeigt, wie die drei Interaktionsmuster in einem realen Arbeitsvorgang zusammenspielen: Aufgabe: "Prüfe Apparat P-4711, kläre Motor-Zuordnung und KV-Verteilung" 1. CAFM-OBJ öffnen (TreeView-Klick: amedCafmExplorer → Equipment) → Grid zeigt alle Assets → Filter: item_number = 'P-4711' → Zeile auswählen → VGrid zeigt Properties 2. Detail-Abschnitt "Referenz-Motoren" (eingebettetes Grid, read-only) → 2 Motoren: M-4711-A (15 kW, KV03), M-4711-B (22 kW, KV03) → Doppelklick auf M-4711-A 3. NEUER TAB: Motors-View öffnet sich → Motor M-4711-A vorselektiert → VGrid: Leistung, Drehzahl, Hersteller, Bauform, Ex-Schutz → Referenz: "KV-Verteilung: KV03-Feld2-Abgang7" 4. Klick auf "KV-Verteilung" → NEUER TAB: CAFM-EMR → TreeList springt zu KV03 > Feld2 > Abgang7 → Grid zeigt Belegung: M-4711-A = 15 kW, Sicherung 25A 5. Zurück zu Tab "CAFM-OBJ" (Tab-Klick) → Kontext unverändert: P-4711 selektiert, Referenz-Motoren sichtbar **Ergebnis:** Der Benutzer hat in einem zusammenhängenden Arbeitsvorgang drei Views (OBJ → Motors → EMR) genutzt — jeder Tab-Sprung ist kontextbezogen (Entität vorselektiert), und die Rückkehr per Tab-Klick stellt den Ausgangskontext sofort wieder her. ===== Legacy-Referenz: DevicesMain (.NET 8) ===== Das .NET 8 Apparaten-Modul (''Amed.Win.Devices'') zeigt das Leading Pattern bereits im Legacy-Code — allerdings mit DockPanels statt Flyout-Drawern und mit separaten Fenstern statt Tab-Navigation. ==== Komposition ==== ''DevicesMain'' (RibbonForm) komponiert 3 DockPanels und 3 UserControls: DevicesMain (RibbonForm) ├── dockPanelMain [Fill] → DeviceListView (BandedGrid + eingebettete VGrid) ├── dockPanelMotors [Left] → MotorsPoolView (Motorenpool-Grid) └── dockPanelAppMotors[Bottom] → DeviceMotorView (Gekoppelte Motoren, BandedGrid) Separate Fenster: ├── DevicesDetailView → VGridControl (8 CategoryRows) └── DevicesWindowKV → KV-Belegung (BandedGrid) ==== Kopplung (Event-Delegates) ==== // DevicesMain.cs, Zeile 57-63: deviceListView.FocusedAppChanged = deviceMotorView.FilterMotors; deviceListView.IdBetrChanged = deviceMotorView.SetIdBetr; deviceListView.RowChanged = motorsPoolView.SetIDBetr; deviceListView.ErwAppNrChanged = motorsPoolView.SetErwAppNr; motorsPoolView.RefreshMotorData = deviceMotorView.RefreshData; deviceMotorView.RefreshMotorPool = motorsPoolView.RefreshData; ==== VGrid: CategoryRows (DevicesDetailView) ==== ^ Category ^ Felder (Beispiele) ^ | Kennungen | AppNr, erwAppNr, DIN-Kennung, Alkylose, R&I, Typ, AnlageZweig | | Allgemeines | Gebaeude, Etage, TA-Luft, KV-aktiv, Qualitaetsnorm | | Bestellung | Bestelldatum, Bestellnummer | | Zeichnung | Zeichnungsdatum, Zeichnungsnummer | | Pruefprotokolle | Protokolldatum, Protokollnummer | | Betriebsanweisung | BA-Datum, BA-Nummer | | Ersatzteilbestellung | ET-Datum, ET-Bestellnummer | | Technische Merkmale | Hauptwerkstoff, Inhalt, Druck, Temperatur, DSF, Filterfläche... | ==== Migration: Legacy → WvdS ==== ^ Legacy (DockPanel/Window) ^ WvdS (Master-Detail-Flyout) ^ | ''dockPanelMain'' + DeviceListView | **Master** (links): TWvdSGridControl | | ''DevicesDetailView'' (8 CategoryRows) | **Detail** (rechts): TWvdSVerticalGrid (gleiche Gruppen) | | ''dockPanelMotors'' + MotorsPoolView | **Flyout-Drawer**: Motor-Zuordnung (Pool-Auswahl) | | ''dockPanelAppMotors'' + DeviceMotorView | **Eingebettetes Grid**: Detail-Abschnitt "Referenz-Motoren" + **Neuer Tab**: Motor-View mit Vorauswahl | | ''DevicesWindowKV'' (separates Fenster) | **Neuer Tab**: CAFM-EMR View, KV vorselektiert | | ''toggleDetails'' (Ribbon-Toggle) | **Detail** zeigt/versteckt sich per Splitter | | ''toggleMotors'' (Ribbon-Toggle) | **Flyout-Drawer** öffnet/schließt sich | ==== Referenzsprung-Kette ==== Das Apparaten-Formular unterstützt die vollständige Arbeitsvorgangabwicklung durch eine Kette von eingebetteten Grids und Referenzsprüngen: CAFM-OBJ: Apparat P-4711 (ObjectDetail) │ ├── VGrid: Eigenschaften (Kennungen, Allgemeines, Technische Merkmale...) │ ├── Eingebettetes Grid: "Referenz-Motoren" │ ├── M-4711-A (15 kW, KV03-Feld2-Abg7) │ └── M-4711-B (22 kW, KV03-Feld2-Abg12) │ │ │ ├── Klick auf Motor → NEUER TAB: Motors-View │ │ └── Motor M-4711-A vorselektiert │ │ └── Motor-Detail: Hersteller, Typ, Bauform... │ │ │ └── Klick auf KV-Spalte → NEUER TAB: CAFM-EMR │ └── KV03 > Feld2 > Abgang7 vorselektiert │ └── Belegung: M-4711-A = 15 kW, Sicherung 25A │ └── Eingebettetes Grid: "Prüfhistorie" └── Klick auf Prüfung → NEUER TAB: PIMS-INSP (InspResult) **Prinzip:** Jede Referenz in einem eingebetteten Grid ist ein potenzieller Tab-Sprung. Der Benutzer entscheidet, ob er im aktuellen Kontext bleibt (nur lesen) oder zum Ziel springt (bearbeiten). Die Referenz-Grids sind **read-only Übersichten** — die Bearbeitung findet immer im zuständigen Topic statt. ==== Wesentliche Verbesserung ==== Im Legacy: 3 DockPanels + 2 separate Fenster = 5 Kontexte, zwischen denen der Benutzer manuell wechselt. Motor-KV-Verteilung erfordert ein separates Fenster (DevicesWindowKV), das keinen Rückbezug zum Apparat hat. In WvdS: 1 View mit eingebetteten Referenz-Grids + Tab-Sprünge = durchgängiger Arbeitsvorgang. Jeder Sprung ist **kontextbezogen** (Motor/KV vorselektiert), und die Rückkehr per Tab-Klick stellt den Ausgangskontext sofort wieder her.