Add WPF UI alongside WinForms; improve cancellation logic

Introduced MainWindow.xaml and code-behind for a modern WPF interface with tabbed settings. Enabled WPF in project file. Refactored startup to launch WPF or WinForms UI based on availability. Registered WPF MainWindow in DI. Improved DataModel cancellation to be synchronous and log exceptions. Minor logging and comment updates. App now supports both WPF and WinForms frontends.
This commit is contained in:
MaddoScientisto 2026-02-15 11:14:19 +01:00
commit 10cc574acb
5 changed files with 484 additions and 10 deletions

View file

@ -7,6 +7,7 @@ using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Logging.Console;
using System.IO;
using Microsoft.Extensions.Options;
namespace ImageCatalog_2;
@ -70,12 +71,32 @@ static class Program
ServiceProvider = serviceCollection.BuildServiceProvider();
var mainForm = ServiceProvider.GetRequiredService<MainForm>();
//var mainViewModel = ServiceProvider.GetRequiredService<DataModel>();
// Resolve WPF MainWindow when available, otherwise fall back to WinForms MainForm
var serviceProvider = ServiceProvider;
//mainForm.Model = mainViewModel;
// NOTE: By default the app will attempt to run the WPF window when available and fall back
// to the WinForms MainForm. If you want to force the WinForms UI for testing, uncomment
// the block below and comment out the WPF branch.
// -----------------------------------------------------------------------------
// // Force WinForms UI (uncomment to enable)
// var mainForm = serviceProvider.GetRequiredService<MainForm>();
// // If you want to set the DataModel explicitly on the WinForms form use the lines below
// // var mainViewModel = serviceProvider.GetRequiredService<DataModel>();
// // mainForm.Model = mainViewModel;
// Application.Run(mainForm);
// -----------------------------------------------------------------------------
Application.Run(mainForm);
if (serviceProvider.GetService(typeof(ImageCatalog_2.MainWindow)) is ImageCatalog_2.MainWindow wpfMain)
{
// Start WPF app
var app = new System.Windows.Application();
app.Run(wpfMain);
}
else
{
var mainForm = serviceProvider.GetRequiredService<MainForm>();
Application.Run(mainForm);
}
}
private static void ConfigureServices(ServiceCollection services)
@ -117,6 +138,8 @@ static class Program
// Register your forms
services.AddTransient<MainForm>();
// Register WPF MainWindow so it can be resolved with the existing DataModel
services.AddTransient<ImageCatalog_2.MainWindow>();
// Version provider for UI and logging
services.AddSingleton<MaddoShared.IVersionProvider, MaddoShared.VersionProvider>();
@ -153,8 +176,8 @@ public sealed class CustomLoggingFormatter : ConsoleFormatter, IDisposable
public override void Write<TState>(
in LogEntry<TState> logEntry,
IExternalScopeProvider scopeProvider,
TextWriter textWriter)
IExternalScopeProvider? scopeProvider,
TextWriter? textWriter)
{
string? message =
logEntry.Formatter?.Invoke(