L6: IBKRTrader.App.Avalonia -> IBKRTrader.App; letzte WinForms-Spuren raus
Das Suffix ".Avalonia" gab es nur, weil daneben ein WinForms-IBKRTrader.App
stand. Das ist seit L5 weg, also faellt auch das Suffix. Git erkennt alle
Dateien als Umbenennung; Assembly, Wurzel-Namensraum und die
avares://-Ressourcen-URI sind mitgezogen.
Nebeneffekt der Umbenennung: die global::Avalonia-Qualifizierungen entfallen.
Sie waren noetig, weil der Namensraum IBKRTrader.App.Avalonia das
Avalonia-Paket verdeckt hat - ein Ueberbleibsel genau der Namensgebung, die
jetzt weg ist.
Inhaltlich falsch gewordene Aussagen berichtigt - das waren die eigentlichen
Ueberbleibsel, nicht die Kommentare:
- .agents/rules/grundregeln.md schrieb weiterhin "C# .NET 10 WinForms",
RichTextBox-Logging, LauncherForm und PropertyGrid vor. Das ist die Regel,
nach der kuenftig gearbeitet wird - sie haette die Portierung Stueck fuer
Stueck rueckgaengig gemacht. Jetzt: Avalonia, keine Plattform-Suffixe, die
11er-Pinnung mit Begruendung, dazu die beiden Regeln, die uns in L1b am
meisten gekostet haben (UTC persistieren + AppTimeZone statt DateTime.Now;
jede Formatierung mit ausdruecklichem IFormatProvider).
- Core: LogEntry ("wird in RichTextBox geschrieben"), IWorker/WorkerEngine/
WorkerInfo ("DataGridView-Zeile"/"-Binding"), ModuleView ("die
WinForms-Shell castet auf Form").
- Doku: ARCHITECTURE (Modul-Ui-Ordner, "designbare Forms mit Initialize"),
KONZEPT-Modul-Accounting ("UI (WinForms, ein Fenster mit Tabs)").
BEWUSST STEHEN GEBLIEBEN sind die Kommentare, die WinForms nur als
Begruendung nennen - warum LoggingService ein Ereignis hat statt einer
RichTextBox, warum ModuleView Func<object> liefert, warum es benannte
Record-Zeilentypen gibt, warum die Einstellungsmaske aus Attributen entsteht.
Das ist die Herleitung des heutigen Entwurfs; ohne sie sieht spaeter jede
dieser Stellen nach Umstaendlichkeit ohne Grund aus.
KONZEPT-Linux-Portierung.md bekommt einen Statusvermerk: umgesetzt, die
Pfadangaben im Fundstellenverzeichnis beziehen sich auf den alten Aufbau.
Zwei Abweichungen von der Schaetzung sind dort festgehalten - der geringere
Aufwand dank der PolytraderSharp-Vorlage, und dass die dort empfohlene
InvariantGlobalization ein Fehler gewesen waere.
Verifiziert: Build 0 Fehler/0 Warnungen, 193 Tests gruen, Smoke-UI
konstruiert alle 7 Ansichten + Launcher + Dialog, Daemon-Prueflauf OK,
publish -r linux-x64 fuer beide Einstiegspunkte fehlerfrei.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -17,24 +17,43 @@ Keine gegenseitigen Blockierungen – alles thread-sicher und performant
|
||||
|
||||
Technik (fest):
|
||||
|
||||
C# .NET 10 WinForms
|
||||
C# .NET 10, **Avalonia** für die Oberfläche – plattformneutral (Windows und Linux).
|
||||
KEIN WinForms und kein System.Drawing: beides bindet an Windows. Alle Projekte sind `net10.0`
|
||||
ohne Plattform-Suffix; ein `net10.0-windows` irgendwo ist ein Fehler.
|
||||
Avalonia bleibt auf der 11er-Linie (11.3.19 / DataGrid 11.3.13), bis LiveCharts2 Avalonia 12
|
||||
unterstützt – sonst brechen die Diagramme der kommenden Module.
|
||||
MySQL – Zugangsdaten NUR in settings.json (gitignored), NIE im Repo/Code/Doku hinterlegen
|
||||
IBKR TWS/Gateway API (Paper: Port 4002, Live: Port 4001 – Umschaltung über TradingSettings.Mode)
|
||||
Interne REST-API + lokaler Webserver (für späteres Web-UI)
|
||||
Settings: settings.json (Vorlage: settings.example.json)
|
||||
Logging: RichTextBox (rtb_logs) + Dateien unter Logs\[Modul]\[Level]-dd-MM-yy.txt (Info/Warn/Error)
|
||||
Logging: LoggingService meldet Einträge über das Ereignis `EntryWritten` (die Oberfläche hängt sich
|
||||
ein und färbt selbst) + Dateien unter Logs/[Modul]/[Level]-dd-MM-yy.txt sowie Logs/[Datum].jsonl
|
||||
Zeit: Zeitstempel IMMER in UTC persistieren. Für Anzeige, Tagesgrenzen und Zeitpläne
|
||||
`AppTimeZone` verwenden, NIE `DateTime.Now` oder `DateTimeKind.Local` – wir betreiben Instanzen
|
||||
in EU und US, die Ortszeit darf nicht am Rechner hängen.
|
||||
Kultur: Jede Zahl-/Datumsformatierung und jedes Parsen braucht einen ausdrücklichen
|
||||
IFormatProvider (i. d. R. InvariantCulture). Ohne ihn hängt das Ergebnis an der Kultur des Hosts.
|
||||
Tests: eigenes Projekt IBKRTrader.Tests (xUnit + NSubstitute + FluentAssertions), NUR Unit-Tests,
|
||||
alles Externe (DB/IBKR/Scraper) gemockt. DoD jeder Phase: `dotnet test` grün + Build sauber.
|
||||
|
||||
UI-Grundmodell (Launcher-Prinzip nach Polytrader):
|
||||
|
||||
LauncherForm = Basis-Fenster. Enthält: Core-Status/Steuerung ("Trading aktivieren", Paper/Live),
|
||||
Workers/Services (dgv_workerlist), Logs (rtb_logs), Settings (PropertyGrid) und eine Modul-Liste.
|
||||
Jedes Modul wird als EIGENSTÄNDIGES Fenster aus dem Launcher geöffnet (nicht als Tab).
|
||||
Der Launcher trackt offene Fenster (Key → Form) und fokussiert bei erneutem Öffnen.
|
||||
dgv_workerlist Spalten: Active | Type | Module | Workername | Last Runtime | Next Runtime | Run Every | Info
|
||||
LauncherWindow = Basis-Fenster mit einer Schaltfläche je registrierter Ansicht und dem
|
||||
gemeinsamen Fenster-Menü. Die Inhalte (Dashboard, Workers, Logs, Settings, Modul-Fenster) sind
|
||||
eigenständige Fenster, keine Tabs; je Ansicht höchstens eines, erneutes Öffnen fokussiert.
|
||||
Layout deklarativ in .axaml, nicht zur Laufzeit im Code. Kompilierte Bindings sind aktiv, jeder
|
||||
Datenkontext braucht ein x:DataType – dadurch fallen Bindungsfehler beim Kompilieren auf.
|
||||
Module tragen KEINEN UI-Code: sonst müssten sie Avalonia referenzieren und wären nicht mehr
|
||||
kopflos lauffähig. Ihr RegisterUi bleibt leer, die Fenster registriert die Shell zentral in
|
||||
src/IBKRTrader.App/Shell/ModuleViews.cs.
|
||||
Workers-Ansicht, Spalten: Aktiv | Typ | Modul | Worker | Letzter Lauf | Nächster Lauf | Intervall | Info
|
||||
Type = "Worker" oder "Service" (Service = permanent laufend)
|
||||
|
||||
Betriebsformen (beide aus derselben Host-Zusammenstellung, src/IBKRTrader.Hosting):
|
||||
|
||||
src/IBKRTrader.App – mit Oberfläche; `--smoke-ui` prüft die Fenster-Konstruktion ohne Anzeigegerät
|
||||
src/IBKRTrader.Daemon – kopflos für Linux/systemd; `--check` fährt die Startprüfungen ohne Dienste
|
||||
|
||||
Core-Worker (müssen zuerst):
|
||||
|
||||
Backup (alle 30 min)
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
# Die Konstruktionsprüfung der Oberfläche braucht mit Avalonia KEIN Anzeigegerät mehr
|
||||
# (SetupWithoutStarting). Mit WinForms war das auf einem Build-Server nicht möglich.
|
||||
- name: Smoke-UI (Fenster-Konstruktion)
|
||||
run: dotnet run --project src/IBKRTrader.App.Avalonia --no-build -c Release -- --smoke-ui
|
||||
run: dotnet run --project src/IBKRTrader.App --no-build -c Release -- --smoke-ui
|
||||
|
||||
# Trockenlauf des kopflosen Dienstes: Host bauen, Startprüfungen fahren, nichts starten.
|
||||
- name: Daemon-Prüflauf
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
dotnet publish src/IBKRTrader.Daemon -c Release -r linux-x64 --self-contained false -o out/daemon
|
||||
dotnet publish src/IBKRTrader.App.Avalonia -c Release -r linux-x64 --self-contained false -o out/gui
|
||||
dotnet publish src/IBKRTrader.App -c Release -r linux-x64 --self-contained false -o out/gui
|
||||
|
||||
- name: Testergebnisse sichern
|
||||
if: always()
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<Project Path="src/IBKRTrader.Core/IBKRTrader.Core.csproj" />
|
||||
<Project Path="src/IBKRTrader.Hosting/IBKRTrader.Hosting.csproj" />
|
||||
<Project Path="src/IBKRTrader.Daemon/IBKRTrader.Daemon.csproj" />
|
||||
<Project Path="src/IBKRTrader.App.Avalonia/IBKRTrader.App.Avalonia.csproj" />
|
||||
<Project Path="src/IBKRTrader.App/IBKRTrader.App.csproj" />
|
||||
<Project Path="src/IBKRTrader.Modules.CongressTrading/IBKRTrader.Modules.CongressTrading.csproj" />
|
||||
<Project Path="src/IBKRTrader.Modules.Accounting/IBKRTrader.Modules.Accounting.csproj" />
|
||||
<Project Path="src/IBKRTrader.Modules.Supervisor/IBKRTrader.Modules.Supervisor.csproj" />
|
||||
|
||||
@@ -8,7 +8,7 @@ PolytraderSharp (nur IBKR statt Polymarket).
|
||||
|
||||
## Architektur (Kurzform)
|
||||
```
|
||||
src/IBKRTrader.App.Avalonia Oberfläche (Avalonia, plattformneutral)
|
||||
src/IBKRTrader.App Oberfläche (Avalonia, plattformneutral)
|
||||
src/IBKRTrader.Daemon kopfloser Dienst (systemd) – dieselbe Anwendung ohne Fenster
|
||||
src/IBKRTrader.Hosting Host-Zusammenstellung, von beiden Einstiegspunkten geteilt
|
||||
src/IBKRTrader.Core Contracts, EF-Persistenz, Trading-Kern, Worker, Security
|
||||
@@ -36,12 +36,12 @@ dotnet test IBKRTrader.slnx
|
||||
|
||||
Anwendung starten:
|
||||
```bash
|
||||
dotnet run --project src/IBKRTrader.App.Avalonia
|
||||
dotnet run --project src/IBKRTrader.App
|
||||
```
|
||||
|
||||
Prüfläufe – beide ohne Anzeigegerät und ohne laufende Dienste, also CI-tauglich:
|
||||
```bash
|
||||
dotnet run --project src/IBKRTrader.App.Avalonia -- --smoke-ui
|
||||
dotnet run --project src/IBKRTrader.App -- --smoke-ui
|
||||
dotnet run --project src/IBKRTrader.Daemon -- --check
|
||||
```
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@ nur dass statt Polymarket über IBKR gehandelt wird.
|
||||
|
||||
> **Stand seit der Linux-Portierung (2026-08-07):** Alle Projekte sind `net10.0` ohne
|
||||
> Plattformbindung. Die WinForms-Shell ist entfernt; der letzte Stand liegt im Tag
|
||||
> `winforms-final`. Einstiegspunkte sind jetzt `IBKRTrader.App.Avalonia` (mit Oberfläche) und
|
||||
> `winforms-final`. Einstiegspunkte sind jetzt `IBKRTrader.App` (mit Oberfläche) und
|
||||
> `IBKRTrader.Daemon` (kopflos, systemd); beide bauen ihren Host über `IBKRTrader.Hosting`.
|
||||
> Analyse und Vorgehen: [konzepte/KONZEPT-Linux-Portierung.md](konzepte/KONZEPT-Linux-Portierung.md).
|
||||
|
||||
```
|
||||
src/IBKRTrader.App.Avalonia (WinExe, net10.0) – Oberfläche: Launcher, Shell, Core-Views, Modul-Fenster
|
||||
src/IBKRTrader.App (WinExe, net10.0) – Oberfläche: Launcher, Shell, Core-Views, Modul-Fenster
|
||||
│ Program.cs: Host bauen (Hosting), Startprüfungen, dann Avalonia; --smoke-ui ohne Anzeigegerät
|
||||
│ Shell/: AvaloniaUiHost, CoreViews, ModuleViews, ViewIcons, WindowMenu
|
||||
│ Views/: LauncherWindow, Dashboard/Workers/Logs/Settings, Views/Modules/ (3 Modul-Fenster)
|
||||
@@ -43,7 +43,7 @@ src/IBKRTrader.Hosting (classlib, net10.0) – AppHostBuilder + RunStartu
|
||||
│ ├── CongressTradingModule : IModule
|
||||
│ ├── Persistence/Ef/ eigener DbContext (ct_) + Repos
|
||||
│ ├── Services/ Scraper + Jobs (IHostedService)
|
||||
│ └── Ui/ CongressTradingMainForm (Tabs) via RegisterUi
|
||||
│ └── (kein UI-Code – das Modul-Fenster liegt in der Shell, s. App/Shell/ModuleViews.cs)
|
||||
│
|
||||
└── tests/IBKRTrader.Tests (xUnit, referenziert Core + Module)
|
||||
```
|
||||
@@ -56,9 +56,10 @@ src/IBKRTrader.Hosting (classlib, net10.0) – AppHostBuilder + RunStartu
|
||||
- **Config**: `appsettings.json` + `appsettings.Local.json` (gitignored, hält Connection-String/Secrets).
|
||||
- **Modul-Vertrag** `IModule`: `Name`, `DbPrefix`, `RegisterServices(services, config)`,
|
||||
`RegisterUi(host, sp)`, `StartAsync/StopAsync`, `GetActivationBlocker(config)`.
|
||||
- **UI = Shell + Views**: Core und Module registrieren `ModuleView`s beim `IModuleUiHost`.
|
||||
Der Launcher öffnet je View ein Fenster (Einzelinstanz, Re-Open fokussiert). Gemeinsames
|
||||
„Fenster"-Menü (`WindowMenu`) auf jedem Form. Views sind designbare Forms mit `Initialize(sp)`.
|
||||
- **UI = Shell + Views**: Der Core stellt den toolkit-neutralen Contract (`ModuleView`,
|
||||
`IModuleUiHost`), die Shell setzt ihn in Avalonia um. Der Launcher öffnet je View ein Fenster
|
||||
(Einzelinstanz, erneutes Öffnen fokussiert), jedes Fenster trägt das gemeinsame „Fenster"-Menü.
|
||||
Layout deklarativ in `.axaml`; Module tragen keinen UI-Code.
|
||||
- **Persistenz**: EF Core (Pomelo/MySQL), `AddDbContextFactory`, Repositories hinter Interfaces.
|
||||
- **Sicherheit**: Master-Key + AES-256-GCM-Verschlüsselung von Credentials at-rest; TLS-Warnung.
|
||||
- **Headless-Test**: `--smoke-ui` konstruiert jede View + Launcher ohne Message-Loop.
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# Analyse: Linux-Fähigkeit des IBKRTrader
|
||||
|
||||
> **UMGESETZT am 2026-08-07 (L0–L5).** Dieses Dokument ist die Analyse, die der Portierung
|
||||
> vorausging, und bleibt als Begründung erhalten – es beschreibt den Stand **vor** dem Umbau.
|
||||
> Was tatsächlich gebaut wurde, steht in der Phasen-Checkliste von
|
||||
> [../ARCHITECTURE.md](../ARCHITECTURE.md#l0l5--linux-portierung-avalonia-statt-winforms--2026-08-07);
|
||||
> die Pfadangaben im Fundstellenverzeichnis unten beziehen sich auf den alten Aufbau.
|
||||
>
|
||||
> Zwei Punkte sind gegenüber der Schätzung anders gekommen:
|
||||
> * Der Aufwand lag deutlich unter den veranschlagten 21–25 Personentagen, weil PolytraderSharp
|
||||
> dieselbe Portierung bereits durchlaufen hatte und als Vorlage diente (Avalonia-Pinnung,
|
||||
> toolkit-neutraler Contract, `AppTimeZone`).
|
||||
> * `InvariantGlobalization=true` – in der Analyse noch als Empfehlung für ein schlankes Image
|
||||
> genannt – wäre ein Fehler gewesen: ohne ICU fällt die Auflösung von Windows-Zeitzonen-IDs aus
|
||||
> und die feste `de-DE`-Formatierung des PDF-Exports kippt auf invariant. Beides lautlos.
|
||||
> Der Daemon setzt es deshalb ausdrücklich auf `false`.
|
||||
|
||||
> Stand: 2026-08-06. **Reine Analyse – es wurde kein Code geändert.**
|
||||
> Grundlage ist der Commit `b96a207` (main): 154 C#-Dateien, ~16.200 LOC, 6 Projekte, 165 Tests.
|
||||
> Alle Aussagen in Abschnitt 1–9 sind am Quelltext bzw. an einem Probe-Restore verifiziert;
|
||||
|
||||
@@ -56,7 +56,7 @@ Registrierung in `Program.cs`. Referenziert nur den Core. Eigener `AccountingDbC
|
||||
`PdfExporter` (PDFsharp/MigraDoc, MIT).
|
||||
- Realisierte GuV nutzt den Core-`RealizedPnlEngine` (FIFO) — kein Duplikat.
|
||||
|
||||
## 5. UI (WinForms, ein Fenster mit Tabs)
|
||||
## 5. UI (Avalonia, ein Fenster mit Registerkarten)
|
||||
Übersicht/BWA (KPI-Kacheln + Monatsvergleich, Zeitraum-/Konto-/Währungswahl), Ledger (filterbar),
|
||||
Steuer (Platzhalter, s. u.), Abrechnung/Export (CSV/PDF), Abruf/Status (Ingest-Läufe, Soll-Ist, manueller
|
||||
Trigger). DB-Zugriff nur auf Interaktion (Smoke-UI-sicher).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="IBKRTrader.App.Avalonia.App"
|
||||
x:Class="IBKRTrader.App.App"
|
||||
RequestedThemeVariant="Light">
|
||||
|
||||
<Application.Styles>
|
||||
@@ -2,12 +2,12 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.Views;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.Views;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia;
|
||||
namespace IBKRTrader.App;
|
||||
|
||||
/// <summary>
|
||||
/// Avalonia-Anwendungsobjekt. Verbindet den bereits laufenden Generic Host (Trading-Dienste,
|
||||
+5
-5
@@ -1,15 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Plattformneutrale Oberfläche: dieselbe Anwendung läuft unter Windows und Linux. Hat die
|
||||
frühere WinForms-Shell (IBKRTrader.App, net10.0-windows) abgelöst; deren letzter Stand
|
||||
liegt im Git-Tag winforms-final. -->
|
||||
<!-- Plattformneutrale Oberfläche: dieselbe Anwendung läuft unter Windows und Linux.
|
||||
WinExe unterdrückt nur das Konsolenfenster unter Windows – mit WinForms hat das nichts
|
||||
zu tun. Der letzte Stand vor der Portierung liegt im Git-Tag winforms-final. -->
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AssemblyName>IBKRTrader.App.Avalonia</AssemblyName>
|
||||
<RootNamespace>IBKRTrader.App.Avalonia</RootNamespace>
|
||||
<AssemblyName>IBKRTrader.App</AssemblyName>
|
||||
<RootNamespace>IBKRTrader.App</RootNamespace>
|
||||
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
|
||||
<!-- Layout wird deklarativ in .axaml gebaut, nicht zur Laufzeit im Code. Kompilierte Bindings
|
||||
verlangen ein x:DataType je Datenkontext – dafür fallen Tippfehler in Bindings beim
|
||||
@@ -1,12 +1,12 @@
|
||||
using Avalonia;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia;
|
||||
namespace IBKRTrader.App;
|
||||
|
||||
/// <summary>
|
||||
/// Einstiegspunkt der plattformneutralen Oberfläche.
|
||||
+4
-3
@@ -1,9 +1,10 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using IBKRTrader.App.Avalonia.Views;
|
||||
using IBKRTrader.App.Views;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>
|
||||
/// Avalonia-Umsetzung von <see cref="IModuleUiHost"/>. Verhält sich wie der frühere
|
||||
@@ -99,7 +100,7 @@ public sealed class AvaloniaUiHost : IModuleUiHost
|
||||
ShutdownConfirmed = true;
|
||||
CloseAllViews();
|
||||
|
||||
if (global::Avalonia.Application.Current?.ApplicationLifetime
|
||||
if (Application.Current?.ApplicationLifetime
|
||||
is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
desktop.Shutdown();
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
using IBKRTrader.App.Avalonia.Views;
|
||||
using IBKRTrader.App.Views;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Settings;
|
||||
@@ -7,7 +7,7 @@ using IBKRTrader.Core.Workers;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>Registriert die Core-Ansichten (Dashboard, Workers, Logs, Settings) bei der Shell.</summary>
|
||||
public static class CoreViews
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
using IBKRTrader.App.Avalonia.Views.Modules;
|
||||
using IBKRTrader.App.Views.Modules;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Trading;
|
||||
@@ -11,7 +11,7 @@ using IBKRTrader.Modules.Supervisor.Persistence;
|
||||
using IBKRTrader.Modules.Supervisor.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>
|
||||
/// Registriert die Fenster der Module bei der Shell.
|
||||
+1
-1
@@ -2,7 +2,7 @@ using IBKRTrader.Core.Modularity;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>
|
||||
/// Die Dienste, die es nur mit Oberfläche gibt. Alles andere kommt aus
|
||||
@@ -1,11 +1,11 @@
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Avalonia.Views;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.App.Views;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Settings;
|
||||
using IBKRTrader.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>
|
||||
/// Konstruktionsprüfung aller Fenster – ohne Message-Loop und ohne laufende Dienste.
|
||||
+2
-2
@@ -3,7 +3,7 @@ using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>
|
||||
/// Löst die toolkit-neutralen <see cref="ModuleView.IconKey"/>-Schlüssel gegen die
|
||||
@@ -48,7 +48,7 @@ public static class ViewIcons
|
||||
try
|
||||
{
|
||||
using var stream = AssetLoader.Open(
|
||||
new Uri($"avares://IBKRTrader.App.Avalonia/Assets/{file}"));
|
||||
new Uri($"avares://IBKRTrader.App/Assets/{file}"));
|
||||
return new Bitmap(stream);
|
||||
}
|
||||
catch
|
||||
+1
-1
@@ -5,7 +5,7 @@ using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Shell;
|
||||
namespace IBKRTrader.App.Shell;
|
||||
|
||||
/// <summary>
|
||||
/// Baut das gemeinsame Fenster-Menü, das auf JEDEM Fenster erscheint und das Wechseln zwischen
|
||||
+4
-2
@@ -1,4 +1,6 @@
|
||||
namespace IBKRTrader.App.Avalonia.ViewModels;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace IBKRTrader.App.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// Zeilentypen für die DataGrids der Core-Ansichten.
|
||||
@@ -15,7 +17,7 @@ public sealed record ModuleRow(string Name, string Prefix, string Status);
|
||||
/// Eine Zeile im Live-Log. Die Farbe hängt am Eintrag statt an einer Selektion – WinForms färbte
|
||||
/// über <c>SelectionColor</c> der RichTextBox ein, in Avalonia wird je Element gebunden.
|
||||
/// </summary>
|
||||
public sealed record LogRow(string Text, global::Avalonia.Media.IBrush Color);
|
||||
public sealed record LogRow(string Text, IBrush Color);
|
||||
|
||||
/// <summary>Eine offene Position im Modul-Fenster.</summary>
|
||||
public sealed record PositionRow(string Symbol, int Quantity, decimal AvgPrice, decimal Notional);
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.ViewModels;
|
||||
namespace IBKRTrader.App.ViewModels;
|
||||
|
||||
/// <summary>Ein bearbeitbares Einzelfeld der Einstellungen.</summary>
|
||||
public sealed class SettingsField
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dg="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.DataGrid"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.Avalonia.ViewModels"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.DashboardWindow"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.ViewModels"
|
||||
x:Class="IBKRTrader.App.Views.DashboardWindow"
|
||||
Title="Dashboard"
|
||||
Width="960" Height="600"
|
||||
MinWidth="640" MinHeight="420"
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Settings;
|
||||
using IBKRTrader.Core.Time;
|
||||
@@ -10,7 +10,7 @@ using IBKRTrader.Core.Trading;
|
||||
using IBKRTrader.Core.Workers;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views;
|
||||
namespace IBKRTrader.App.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Core-Ansicht: Gesamtüberblick (Handelsmodus, aggregierte Kennzahlen, geladene Module).
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.LauncherWindow"
|
||||
x:Class="IBKRTrader.App.Views.LauncherWindow"
|
||||
Title="IBKRTrader — Launcher"
|
||||
Width="820" Height="560"
|
||||
MinWidth="560" MinHeight="360"
|
||||
+4
-3
@@ -1,12 +1,13 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.Core.Time;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views;
|
||||
namespace IBKRTrader.App.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Launcher – das Basisfenster der Shell. Zeigt je registrierter View eine Schaltfläche und trägt
|
||||
@@ -78,7 +79,7 @@ public partial class LauncherWindow : Window
|
||||
HorizontalAlignment = HorizontalAlignment.Center
|
||||
});
|
||||
|
||||
var button = new Button { Content = content, Padding = new global::Avalonia.Thickness(10, 6) };
|
||||
var button = new Button { Content = content, Padding = new Thickness(10, 6) };
|
||||
button.Click += (_, _) => _uiHost.OpenView(id);
|
||||
|
||||
_viewButtons[id] = button;
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.Avalonia.ViewModels"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.LogsWindow"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.ViewModels"
|
||||
x:Class="IBKRTrader.App.Views.LogsWindow"
|
||||
Title="Logs"
|
||||
Width="1000" Height="650"
|
||||
MinWidth="640" MinHeight="360"
|
||||
+3
-3
@@ -4,13 +4,13 @@ using Avalonia.Input.Platform;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Threading;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Time;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views;
|
||||
namespace IBKRTrader.App.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Core-Ansicht: Live-Log, an das <see cref="LoggingService.EntryWritten"/>-Ereignis gebunden.
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dg="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.DataGrid"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.Avalonia.ViewModels"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.Modules.AccountingWindow"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.ViewModels"
|
||||
x:Class="IBKRTrader.App.Views.Modules.AccountingWindow"
|
||||
Title="Accounting"
|
||||
Width="1100" Height="720"
|
||||
MinWidth="820" MinHeight="520"
|
||||
+3
-3
@@ -2,8 +2,8 @@ using System.Globalization;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Platform.Storage;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Time;
|
||||
@@ -11,7 +11,7 @@ using IBKRTrader.Modules.Accounting.Logic;
|
||||
using IBKRTrader.Modules.Accounting.Persistence;
|
||||
using IBKRTrader.Modules.Accounting.Services;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views.Modules;
|
||||
namespace IBKRTrader.App.Views.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Fenster des Accounting-Moduls: Übersicht/BWA, Ledger, Steuer (Platzhalter),
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dg="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.DataGrid"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.Avalonia.ViewModels"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.Modules.CongressTradingWindow"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.ViewModels"
|
||||
x:Class="IBKRTrader.App.Views.Modules.CongressTradingWindow"
|
||||
Title="Congress Trading"
|
||||
Width="920" Height="620"
|
||||
MinWidth="640" MinHeight="420"
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Time;
|
||||
@@ -10,7 +10,7 @@ using IBKRTrader.Core.Workers;
|
||||
using IBKRTrader.Modules.CongressTrading;
|
||||
using IBKRTrader.Modules.CongressTrading.Database;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views.Modules;
|
||||
namespace IBKRTrader.App.Views.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Fenster des CongressTrading-Moduls: DB-Kennzahlen, manueller Scrape-Auslöser und die offenen
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dg="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.DataGrid"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.Avalonia.ViewModels"
|
||||
xmlns:vm="clr-namespace:IBKRTrader.App.ViewModels"
|
||||
xmlns:sup="clr-namespace:IBKRTrader.Modules.Supervisor.Services;assembly=IBKRTrader.Modules.Supervisor"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.Modules.SupervisorWindow"
|
||||
x:Class="IBKRTrader.App.Views.Modules.SupervisorWindow"
|
||||
Title="Supervisor"
|
||||
Width="1120" Height="760"
|
||||
MinWidth="820" MinHeight="540"
|
||||
+3
-3
@@ -2,8 +2,8 @@ using System.Text.Json;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Threading;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.Core.Analytics;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
@@ -12,7 +12,7 @@ using IBKRTrader.Modules.Supervisor.Agent;
|
||||
using IBKRTrader.Modules.Supervisor.Persistence;
|
||||
using IBKRTrader.Modules.Supervisor.Services;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views.Modules;
|
||||
namespace IBKRTrader.App.Views.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Fenster des Supervisor-Moduls: Analyse (Chat mit dem Agenten, Tool-Aufrufe sichtbar),
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.SettingsWindow"
|
||||
x:Class="IBKRTrader.App.Views.SettingsWindow"
|
||||
Title="Settings"
|
||||
Width="860" Height="740"
|
||||
MinWidth="620" MinHeight="420"
|
||||
+3
-3
@@ -3,13 +3,13 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Avalonia.ViewModels;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.App.ViewModels;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Settings;
|
||||
using IBKRTrader.Core.Time;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views;
|
||||
namespace IBKRTrader.App.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Core-Ansicht: Einstellungen. Ersetzt das <c>PropertyGrid</c> der WinForms-Fassung durch eine
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.ShutdownConfirmWindow"
|
||||
x:Class="IBKRTrader.App.Views.ShutdownConfirmWindow"
|
||||
Title="Beenden"
|
||||
Width="440" SizeToContent="Height"
|
||||
CanResize="False"
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views;
|
||||
namespace IBKRTrader.App.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Sicherheitsabfrage vor dem Beenden. Ersetzt <c>MessageBox.Show</c> – Avalonia bringt keinen
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:dg="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls.DataGrid"
|
||||
xmlns:w="clr-namespace:IBKRTrader.Core.Workers;assembly=IBKRTrader.Core"
|
||||
x:Class="IBKRTrader.App.Avalonia.Views.WorkersWindow"
|
||||
x:Class="IBKRTrader.App.Views.WorkersWindow"
|
||||
Title="Workers / Services"
|
||||
Width="1200" Height="700"
|
||||
MinWidth="760" MinHeight="420"
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using IBKRTrader.App.Avalonia.Shell;
|
||||
using IBKRTrader.App.Shell;
|
||||
using IBKRTrader.Core.Modularity;
|
||||
using IBKRTrader.Core.Time;
|
||||
using IBKRTrader.Core.Workers;
|
||||
|
||||
namespace IBKRTrader.App.Avalonia.Views;
|
||||
namespace IBKRTrader.App.Views;
|
||||
|
||||
/// <summary>
|
||||
/// Core-Ansicht: Worker- und Service-Übersicht, live an die <see cref="WorkerEngine"/> gebunden.
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Plattformneutral: derselbe Core läuft unter Windows und Linux. Der UI-Contract
|
||||
(ModuleView/IModuleUiHost) ist toolkit-neutral (Func<object> statt Func<Form>, IconKey
|
||||
statt System.Drawing.Image) – hier hängt weder WinForms noch System.Drawing.Common,
|
||||
letzteres ist seit .NET 7 Windows-only und wirft auf Linux. -->
|
||||
(ModuleView/IModuleUiHost) ist toolkit-neutral (Func<object> statt eines Fenstertyps,
|
||||
IconKey statt System.Drawing.Image) – hier hängt kein UI-Toolkit und kein
|
||||
System.Drawing.Common, letzteres ist seit .NET 7 Windows-only und wirft auf Linux. -->
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace IBKRTrader.Core.Logging;
|
||||
|
||||
/// <summary>Immutable log entry – wird in Datei und RichTextBox geschrieben.</summary>
|
||||
/// <summary>Unveränderlicher Logeintrag – geht in die Logdateien und an alle Senken.</summary>
|
||||
public sealed record LogEntry(
|
||||
DateTime Timestamp,
|
||||
AppLogLevel Level,
|
||||
|
||||
@@ -9,8 +9,7 @@ namespace IBKRTrader.Core.Modularity;
|
||||
/// Dadurch trägt der Core keine UI-Abhängigkeit und bleibt plattformneutral – Voraussetzung für den
|
||||
/// kopflosen Linux-Betrieb. Insbesondere hängt hier kein <c>System.Drawing.Image</c> mehr:
|
||||
/// <c>System.Drawing.Common</c> ist seit .NET 7 Windows-only und wirft auf Linux. Die jeweilige
|
||||
/// Shell kennt ihr Toolkit und castet – die WinForms-Shell auf <c>Form</c>, die Avalonia-Shell
|
||||
/// auf <c>Window</c>.</para>
|
||||
/// Shell kennt ihr Toolkit und castet – die Avalonia-Shell auf <c>Window</c>.</para>
|
||||
/// </summary>
|
||||
public sealed class ModuleView
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ public interface IWorker
|
||||
/// <summary>Worker = periodisch / Service = dauerhaft.</summary>
|
||||
WorkerType Type { get; }
|
||||
|
||||
/// <summary>Live-Daten für die DataGridView-Zeile.</summary>
|
||||
/// <summary>Live-Daten für die Zeile in der Workers-Ansicht.</summary>
|
||||
WorkerInfo Info { get; }
|
||||
|
||||
/// <summary>Löst einen sofortigen, manuellen Run aus (unabhängig vom Zeitplan).</summary>
|
||||
|
||||
@@ -13,7 +13,11 @@ public class WorkerEngine
|
||||
{
|
||||
private readonly ConcurrentDictionary<string, IWorker> _registry = new();
|
||||
|
||||
/// <summary>Live-bindbare Liste für die Workers-Ansicht (DataGridView).</summary>
|
||||
/// <summary>
|
||||
/// Live-bindbare Liste für die Workers-Ansicht. Die Liste selbst ändert sich zur Laufzeit
|
||||
/// nicht – die Worker werden hier einmal registriert; was sich ändert, meldet
|
||||
/// <see cref="WorkerInfo"/> über INotifyPropertyChanged.
|
||||
/// </summary>
|
||||
public BindingList<WorkerInfo> WorkerInfos { get; } = [];
|
||||
|
||||
public WorkerEngine(IEnumerable<IWorker> workers, LoggingService logger)
|
||||
|
||||
@@ -4,8 +4,8 @@ using System.Runtime.CompilerServices;
|
||||
namespace IBKRTrader.Core.Workers;
|
||||
|
||||
/// <summary>
|
||||
/// ViewModel-Objekt für eine Zeile in dgv_workerlist.
|
||||
/// Implementiert INotifyPropertyChanged für automatisches DataGridView-Binding.
|
||||
/// ViewModel-Objekt für eine Zeile der Workers-Ansicht.
|
||||
/// Implementiert INotifyPropertyChanged, damit die Oberfläche Änderungen ohne Zutun übernimmt.
|
||||
/// </summary>
|
||||
public class WorkerInfo : INotifyPropertyChanged
|
||||
{
|
||||
@@ -32,8 +32,7 @@ public class WorkerInfo : INotifyPropertyChanged
|
||||
public string RunEvery { get => _runEvery; set => Set(ref _runEvery, value); }
|
||||
public string Info { get => _info; set => Set(ref _info, value); }
|
||||
|
||||
/// <summary>Interner Status – wird nicht direkt als DGV-Spalte verwendet,
|
||||
/// aber steuert die Info-Spalte.</summary>
|
||||
/// <summary>Interner Status – keine eigene Spalte, steuert aber den Info-Text.</summary>
|
||||
public WorkerStatus Status
|
||||
{
|
||||
get => _status;
|
||||
|
||||
Reference in New Issue
Block a user