diff --git a/docs/LEITFADEN-Avalonia-Portierung.md b/docs/LEITFADEN-Avalonia-Portierung.md new file mode 100644 index 0000000..708c2d8 --- /dev/null +++ b/docs/LEITFADEN-Avalonia-Portierung.md @@ -0,0 +1,359 @@ +# Portierungsleitfaden Avalonia (Fortsetzung) + +**Stand:** 06.08.2026 · **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 + + + + + + + +