====== 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.