# Portierungsleitfaden Avalonia (Fortsetzung) **Stand:** 13.08.2026 (A1–A4 abgehakt, Deploymentcenter-Hinweis) · **Zielgruppe:** KI-Agent, der die UI-Portierung fortsetzt **Vorgänger-Dokumente:** [`UI-SPEZIFIKATION-WinForms.md`](UI-SPEZIFIKATION-WinForms.md) (wie die alte Oberfläche aussah), [`ANALYSE-Linux-Portierung.md`](ANALYSE-Linux-Portierung.md) (Gesamtplan) --- ## 0. Was du wissen musst, bevor du irgendetwas anfasst | Punkt | Wert | |---|---| | Projekt | `src/PolyTrader.App.Avalonia` | | Zielframework | `net10.0` | | Avalonia | **11.3.19** — **NICHT auf 12 heben!** LiveCharts2 2.0.5 ist gegen 11 gebaut und wirft unter 12 zur Laufzeit `MissingFieldException: Avalonia.Input.Gestures.PinchEvent`. `Avalonia.Controls.DataGrid` folgt einer eigenen Reihe und steht auf **11.3.13**. | | Diagramme | LiveCharts2 (`LiveChartsCore.SkiaSharpView.Avalonia` 2.0.5) | | Alte Oberfläche | Git-Tag **`winforms-final`** — dort steht der komplette WinForms-Code | | Sprache | Alles auf Deutsch: Beschriftungen, Kommentare, Commit-Nachrichten | ### Der Referenzstand ist eine Tag-Abfrage entfernt ```bash git show winforms-final:Ui/Views/DashboardView.cs git show winforms-final:src/PolyTrader.Modules.CopyTrading/Ui/MasterTradersView.Designer.cs ``` **Nutze das immer**, bevor du eine Ansicht anfasst. Die Spezifikation ist eine Zusammenfassung – der Tag ist die Wahrheit. --- ## 1. Die harten Regeln ### 1.1 Layout ist deklarativ. Immer. > **Jede View besteht aus `View.axaml` (vollständiges Layout) und `View.axaml.cs` (nur Verdrahtung > und Datenlogik). Steuerelemente und Layout werden NIEMALS zur Laufzeit im Code erzeugt.** Das ist Richards ausdrückliche Vorgabe und ersetzt die frühere WinForms-Designer-Regel. Wenn du etwas Dynamisches brauchst (Menüeinträge, Formularfelder), dann so: - Das **Datenmodell** liefert eine Liste (`ObservableCollection`) - Das **XAML** beschreibt über `ItemsControl` + `DataTemplate`, wie ein Element aussieht Vorbilder im Code: [`Controls/WindowMenuBar.axaml`](../src/PolyTrader.App.Avalonia/Controls/WindowMenuBar.axaml) und [`Controls/SettingsEditor.axaml`](../src/PolyTrader.App.Avalonia/Controls/SettingsEditor.axaml). ### 1.2 Keine festen Farben Alle Farben kommen aus den Themen-Ressourcen (`App.axaml`, 18 Token je Variante). Im XAML: ```xml Foreground="{DynamicResource AppMutedTextBrush}" ``` Im Code (nur wo unvermeidbar): ```csharp btn.Background = ThemeManager.Brush("AppToggleActiveBrush"); ``` **Wichtig:** Im Code gesetzte Farben folgen dem Themenwechsel **nicht von selbst**. Wenn du eine setzt, hänge dich an `ThemeManager.ThemeChanged` und zeichne dort neu — und melde dich beim `Closed`-Ereignis wieder ab: ```csharp void OnTheme() => UpdateFarben(); ThemeManager.ThemeChanged += OnTheme; Closed += (_, _) => ThemeManager.ThemeChanged -= OnTheme; ``` Verfügbare Token: `AppSurfaceBrush`, `AppSurfaceAltBrush`, `AppCardBrush`, `AppBorderBrush`, `AppMutedTextBrush`, `AppCaptionTextBrush`, `AppReadOnlyTextBrush`, `AppPositiveBrush`, `AppNegativeBrush`, `AppWarningBrush`, `AppTradeLossBrush`, `AppTradeSmallWinBrush`, `AppTradeBigWinBrush`, `AppToggleActiveBrush`, `AppToggleSellOnlyBrush`, `AppToggleInactiveBrush`, `AppChatUserBrush`, `AppChatAgentBrush`. **Neuen Token gebraucht?** In `App.axaml` in **beiden** `ResourceDictionary`-Blöcken ergänzen und den Schlüssel in die Prüfliste in `Program.RunSmokeUi` aufnehmen. ### 1.3 Keine Dialoge für Erfolgsmeldungen Die WinForms-Fassung bestätigte jedes Speichern mit einer MessageBox. Das ist bewusst abgeschafft: - **Erfolg/Status** → Statuszeile des Fensters (`lblStatus`, `Border Classes="statusbar"`) - **Echte Entscheidung** (Löschen bestätigen, Eingabe erfragen) → `DialogWindow.Confirm` / `.Prompt` - **Fehler, der Handeln erfordert** → `DialogWindow.Info` ### 1.4 Fehlerbehandlung: die Ansicht muss bedienbar bleiben Datenzugriffe immer in `try/catch`. Bei Fehlern die Liste leeren und die Meldung in die Statuszeile schreiben — **nie** die Ansicht mit einer Ausnahme aufreißen: ```csharp try { _rows.Clear(); foreach (var r in repo.GetAll()) _rows.Add(r); } catch (Exception ex) { Status($"Laden fehlgeschlagen: {ex.Message}"); } ``` ### 1.5 Module bleiben frei von Avalonia Die Modul-Fenster liegen in `Views/Modules/` **in der App**, nicht in den Modulprojekten. Grund: Der kopflose Linux-Daemon (`--headless`) soll keine GUI-Bibliothek mitschleppen. Siehe [`Views/Modules/README.md`](../src/PolyTrader.App.Avalonia/Views/Modules/README.md). **Füge NIEMALS eine Avalonia-Paketreferenz zu einem `PolyTrader.Modules.*`-Projekt hinzu.** --- ## 2. Das Baukastenmuster Jedes Fenster folgt demselben Aufbau. Kopiere [`Views/JobsWindow.axaml`](../src/PolyTrader.App.Avalonia/Views/JobsWindow.axaml) als kleinstes Beispiel oder [`Views/Modules/CopyTradingWindow.axaml`](../src/PolyTrader.App.Avalonia/Views/Modules/CopyTradingWindow.axaml) als größtes. ```xml