L6: IBKRTrader.App.Avalonia -> IBKRTrader.App; letzte WinForms-Spuren raus
Build & Test / build (ubuntu-latest) (push) Canceled after 0s
Build & Test / build (windows-latest) (push) Canceled after 0s

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:
Richard
2026-08-07 21:16:48 +02:00
co-authored by Claude Opus 5
parent d86a083438
commit c176b05ea1
45 changed files with 139 additions and 98 deletions
@@ -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,
@@ -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.
@@ -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();
}
@@ -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
@@ -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.
@@ -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.
@@ -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
@@ -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
@@ -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,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
@@ -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"
@@ -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,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"
@@ -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;
@@ -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"
@@ -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.
@@ -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"
@@ -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),
@@ -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"
@@ -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
@@ -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"
@@ -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,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,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,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,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
@@ -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"
@@ -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.
+3 -3
View File
@@ -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&lt;object&gt; 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 -1
View File
@@ -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,
+1 -2
View File
@@ -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
{
+1 -1
View File
@@ -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>
+5 -1
View File
@@ -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)
+3 -4
View File
@@ -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;