Remove legacy WPF app, flatten WinUI project to repo root, rename namespace

The repo carried two parallel UIs (WPF + WinUI) sharing Models/Services via
cross-directory Link includes. Now that WinUI is the only frontend, collapse
the structure so the WinUI project IS the repo root instead of a nested
sibling folder:

- Delete the WPF project entirely (App.xaml, MainWindow.xaml, csproj) and its
  bin/obj output
- Move AmiReel.WinUI/* up to the repo root (App, MainWindow, MainPage,
  DialogHelper, Assets, Package.appxmanifest, app.manifest, Properties,
  .github/instructions, AGENTS.md) via git mv, preserving history
- Rename AmiReel.WinUI.csproj -> AmiReel.csproj; regenerate the solution as
  AmiReel.slnx (the newer XML solution format) with a single project
- Rename namespace AmigaDB.VideoRenderer.{Models,Services} -> AmiReel.{...}
  and AmiReel_WinUI -> AmiReel across all files, including the embedded
  ffmpeg/ffprobe resource logical names in the csproj and ToolExtractor
- Models/ and Services/ no longer need the Link-based cross-directory
  <Compile Include>; they're picked up by the SDK's default globbing now
  that they live under the project directory
- Rename assets/ -> branding/ (source icon art) to avoid a case-insensitive
  collision with Assets/ (packaged tile art) once both sit at repo root
- Merge the two .gitignore files into one; track the PublishProfiles pubxml
  files instead of ignoring them (no secrets, and they keep publish
  reproducible across machines) as branding, gitignore, etc.
- Simplify publish-win-x64.ps1 (drop the -Target Wpf/WinUI switch, there's
  only one target now) and rewrite README.md to describe the single-project
  layout, build/run/publish commands, and file structure

Verified: dotnet build succeeds for both AmiReel.csproj and AmiReel.slnx, and
the built exe launches and renders identically to before the move.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 14:07:10 +02:00
parent 3e881b79b8
commit 603af17e56
66 changed files with 641 additions and 1905 deletions
@@ -0,0 +1,420 @@
---
description: 'WinUI 3 / WinAppSDK architecture, MVVM, XAML patterns, DI, theming, and controls guidance'
applyTo: '**/*.cs, **/*.xaml, **/*.csproj'
---
# WinUI 3 / WinAppSDK -- Best Practices & Patterns
This file covers WinUI 3-specific patterns, conventions, and architecture guidance for this project.
---
## 1. Architecture -- MVVM Pattern
### Overview
Use **Model-View-ViewModel (MVVM)** for all UI features:
| Layer | Responsibility | Example |
|---|---|---|
| **Model** | Data structures & business entities | `Item.cs`, `UserProfile.cs` |
| **View** | XAML UI -- layout, styles, animations | `MainPage.xaml` |
| **ViewModel** | UI state, commands, data transformation | `MainViewModel.cs` |
| **Service** | Business logic, data access, navigation | `IDataService.cs`, `NavigationService.cs` |
### Project Folder Structure
```
<ProjectName>/
Models/ -> Data classes
ViewModels/ -> ViewModels (one per page/dialog)
Views/ -> XAML pages and windows
Services/ -> Business logic & platform services
Converters/ -> IValueConverter implementations
Helpers/ -> Static utility methods
Controls/ -> Custom/reusable controls
Strings/
en-us/
Resources.resw
Assets/ -> Images, icons, splash screens
```
### ViewModel Base
Use `CommunityToolkit.Mvvm` (recommended) for boilerplate-free ViewModels:
```xml
<!-- Use latest stable version; do not hard-code version numbers in instructions -->
<PackageReference Include="CommunityToolkit.Mvvm" Version="*" />
```
```csharp
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class MainViewModel : ObservableObject
{
[ObservableProperty]
private string _title = string.Empty;
[ObservableProperty]
private bool _isLoading;
[RelayCommand]
private async Task LoadDataAsync()
{
IsLoading = true;
try
{
// Load data
}
finally
{
IsLoading = false;
}
}
}
```
### View-ViewModel Binding
```xml
<Page
x:Class="<RootNamespace>.Views.MainPage"
xmlns:vm="using:<RootNamespace>.ViewModels">
<Page.DataContext>
<vm:MainViewModel />
</Page.DataContext>
<Grid>
<TextBlock Text="{x:Bind ViewModel.Title, Mode=OneWay}" />
<Button Command="{x:Bind ViewModel.LoadDataCommand}" Content="Load" />
</Grid>
</Page>
```
---
## 2. XAML Best Practices
### Use `x:Bind` Over `{Binding}`
| Feature | `x:Bind` | `{Binding}` |
|---|---|---|
| Compile-time check | Yes | No |
| Performance | Faster (compiled) | Slower (reflection) |
| Default mode | OneTime | OneWay |
| IntelliSense | Yes | No |
```xml
<!-- GOOD -->
<TextBlock Text="{x:Bind ViewModel.Name, Mode=OneWay}" />
<!-- AVOID -->
<TextBlock Text="{Binding Name}" />
```
### Use `x:Load` for Deferred Loading
```xml
<StackPanel x:Load="{x:Bind ViewModel.ShowAdvancedOptions, Mode=OneWay}">
<!-- Heavy content loaded only when needed -->
</StackPanel>
```
### Use WinUI Controls from the SDK
Prefer the WinUI 3 controls from `Microsoft.UI.Xaml.Controls`, **not** the older UWP `Windows.UI.Xaml.Controls`:
```csharp
// GOOD -- WinUI 3
using Microsoft.UI.Xaml.Controls;
// AVOID -- UWP (won't work in WinUI 3 desktop)
// using Windows.UI.Xaml.Controls;
```
### XAML Formatting Convention
```xml
<Button
x:Name="SaveButton"
x:Uid="SaveButton"
AutomationProperties.Name="Save"
Command="{x:Bind ViewModel.SaveCommand}"
Style="{StaticResource AccentButtonStyle}" />
```
- One attribute per line for controls with 3+ attributes.
- Order: `x:Name` -> `x:Uid` -> `AutomationProperties` -> layout -> data -> style.
---
## 3. Dependency Injection
### Setup with `Microsoft.Extensions.DependencyInjection`
```xml
<!-- Use latest stable version; do not hard-code version numbers in instructions -->
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="*" />
```
```csharp
// App.xaml.cs
public partial class App : Application
{
public static IServiceProvider Services { get; private set; } = null!;
public App()
{
InitializeComponent();
Services = ConfigureServices();
}
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
// Services
services.AddSingleton<INavigationService, NavigationService>();
services.AddTransient<IDataService, DataService>();
// ViewModels
services.AddTransient<MainViewModel>();
return services.BuildServiceProvider();
}
}
```
---
## 4. Navigation
### Frame-based Navigation
```csharp
public interface INavigationService
{
bool CanGoBack { get; }
void NavigateTo<TPage>() where TPage : Page;
void GoBack();
}
```
Use a `NavigationView` with a `Frame`:
```xml
<NavigationView SelectionChanged="OnNavigationChanged">
<NavigationView.MenuItems>
<NavigationViewItem Content="Home" Tag="Home" />
<NavigationViewItem Content="Settings" Tag="Settings" />
</NavigationView.MenuItems>
<Frame x:Name="ContentFrame" />
</NavigationView>
```
---
## 5. Windowing & Title Bar
### Custom Title Bar
```csharp
// In Window constructor or Activated handler
ExtendsContentIntoTitleBar = true;
SetTitleBar(AppTitleBar); // AppTitleBar is a UIElement in your XAML
```
```xml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="48" /> <!-- Title bar -->
<RowDefinition Height="*" /> <!-- Content -->
</Grid.RowDefinitions>
<Grid x:Name="AppTitleBar" Grid.Row="0">
<TextBlock Text="My App" VerticalAlignment="Center" Margin="16,0" />
</Grid>
<Frame Grid.Row="1" x:Name="ContentFrame" />
</Grid>
```
### Window Sizing
```csharp
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
var windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
var appWindow = AppWindow.GetFromWindowId(windowId);
appWindow.Resize(new SizeInt32(1280, 720));
```
---
## 6. Theming
### Support Light/Dark/High Contrast
```xml
<!-- In App.xaml -->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
```
### Detect Theme Changes
```csharp
if (Content is FrameworkElement rootElement)
{
rootElement.ActualThemeChanged += (s, e) =>
{
// React to theme change
};
}
```
### Use Theme Resources, Not Hard-coded Colors
```xml
<!-- GOOD -->
<TextBlock Foreground="{ThemeResource TextFillColorPrimaryBrush}" />
<!-- AVOID -->
<TextBlock Foreground="#000000" />
```
---
## 7. System Backdrop (Mica / Acrylic)
This project uses **Mica** backdrop (already configured in `MainWindow.xaml`):
```xml
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
```
Alternatives:
```xml
<DesktopAcrylicBackdrop /> <!-- Acrylic -->
<MicaBackdrop Kind="BaseAlt" /> <!-- Mica Alt -->
```
---
## 8. Community Toolkit
### Recommended Packages
```xml
<!-- Use latest stable versions; do not hard-code version numbers in instructions -->
<PackageReference Include="CommunityToolkit.Mvvm" Version="*" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="*" />
<PackageReference Include="CommunityToolkit.WinUI.Helpers" Version="*" />
<PackageReference Include="CommunityToolkit.WinUI.Animations" Version="*" />
```
### Useful Toolkit Features
| Feature | Package | Use Case |
|---|---|---|
| `ObservableObject` | CommunityToolkit.Mvvm | ViewModel base class |
| `RelayCommand` | CommunityToolkit.Mvvm | Command implementation |
| `ObservableProperty` | CommunityToolkit.Mvvm | Auto INotifyPropertyChanged |
| `SettingsCard` | CommunityToolkit.WinUI.Controls | Settings pages |
| `IncrementalLoadingCollection` | CommunityToolkit.WinUI | Lazy-loading lists |
---
## 9. Common Pitfalls
| Pitfall | Solution |
|---|---|
| Using `Windows.UI.Xaml` namespace | Use `Microsoft.UI.Xaml` for WinUI 3 |
| Calling `Window.Current` | Not available in WinUI 3 -- pass window reference explicitly |
| Using `CoreDispatcher` | Use `DispatcherQueue` instead |
| `REGDB_E_CLASSNOTREG` error | Ensure Developer Mode is enabled, then re-register: run `winapp unregister` followed by `dotnet run` (or `winapp run <build-output>`) to refresh the loose-layout registration |
| Stale package state after manifest changes | Run `winapp unregister`, then `dotnet run` -- using `winapp run --clean` additionally wipes `LocalState`/settings to test first-run behavior |
| XAML Designer crashes | Clean & rebuild; ensure platform matches (x64 vs AnyCPU) |
| `{Binding}` not updating | Switch to `x:Bind` with `Mode=OneWay` or `Mode=TwoWay` |
---
## 10. Validation
Build & register the MSIX package -- see **Build, Run & Deploy** in `.github/agents/Agents.md`.
### Verify
- Run the app and verify the changed UI renders correctly on x64.
- Search XAML for `{Binding` -- replace with `x:Bind`.
- Search XAML for `Foreground="#` or `Background="#` -- replace with `{ThemeResource}`.
- Search C# for `Windows.UI.Xaml` -- replace with `Microsoft.UI.Xaml`.
- Search C# for `Window.Current` -- replace with explicit window reference.
- Search C# for `CoreDispatcher` -- replace with `DispatcherQueue`.
- Test Light, Dark, and High Contrast themes.
---
## 11. Must Read & Research
> **Agent Rule:** Before making any WinUI/WinAppSDK-related change, you **must** fetch and review the relevant references below using `fetch_webpage`. Consult the appropriate section based on the type of change. Apply what you learn -- do not skip this step.
### Official Documentation
| # | Reference | When to consult |
|---|---|---|
| 1 | [WinUI 3 Overview](https://learn.microsoft.com/en-us/windows/apps/winui/winui3/) | Starting new features, onboarding to the project |
| 2 | [Windows App SDK](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/) | Using SDK-specific APIs (windowing, lifecycle, activation) |
| 3 | [WinUI 3 API Reference](https://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/) | Looking up specific class/method signatures |
| 4 | [WinUI 3 Gallery App](https://learn.microsoft.com/en-us/windows/apps/design/controls/) | Choosing controls, reviewing control patterns |
| 5 | [AI Dev Gallery](https://github.com/microsoft/ai-dev-gallery) | On-device AI/ML integration patterns, model usage examples in WinUI |
| 6 | [Windows App SDK Release Notes](https://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/stable-channel) | Checking for breaking changes, new APIs, known issues |
### Architecture & Patterns
| # | Reference | When to consult |
|---|---|---|
| 7 | [CommunityToolkit.Mvvm Docs](https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/) | Implementing ViewModels, commands, `ObservableProperty` |
| 8 | [Dependency Injection in .NET](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection) | Registering services, constructor injection, lifetime management |
| 9 | [Template Studio for WinUI](https://github.com/microsoft/TemplateStudio) | Scaffolding pages, navigation, project structure patterns |
### Controls & Design
| # | Reference | When to consult |
|---|---|---|
| 10 | [WinUI 3 Gallery (GitHub)](https://github.com/microsoft/WinUI-Gallery) | Example implementations of any WinUI control |
| 11 | [Windows Community Toolkit (GitHub)](https://github.com/CommunityToolkit/Windows) | Before building custom controls -- check if the toolkit already has one |
| 12 | [Fluent Design System](https://learn.microsoft.com/en-us/windows/apps/design/) | Spacing, typography, colour, motion, layout decisions |
| 13 | [XAML Controls Gallery](https://apps.microsoft.com/store/detail/winui-3-gallery/9P3JFPWWDZRC) | Interactive demo of all controls and their properties |
### Windows APIs & AI
| # | Reference | When to consult |
|---|---|---|
| 14 | [Windows APIs instruction file](windows-apis.instructions.md) | **First stop** -- check if a built-in API already exists for the capability you need (AI, windowing, notifications, widgets, lifecycle, etc.) |
| 15 | [Windows AI APIs](https://learn.microsoft.com/en-us/windows/ai/apis/) | On-device AI: Phi Silica (text gen), OCR, imaging (super-res, description, object extract, erase) |
| 16 | [Windows ML](https://learn.microsoft.com/en-us/windows/ai/new-windows-ml/overview) | Custom ONNX model inference on CPU/GPU/NPU |
| 17 | [Foundry Local](https://learn.microsoft.com/en-us/windows/ai/foundry-local/get-started) | Run OSS LLMs (Llama, Mistral, Phi) locally via REST API |
| 18 | [Windows AI on Windows](https://learn.microsoft.com/en-us/windows/ai/) | AI landing page -- all AI options for Windows apps |
### Samples
> **Agent Rule -- MANDATORY:** Before implementing any WinAppSDK or Platform SDK API you have not used before, **search the samples repo first** and study the working example. Do not guess API usage from docs alone -- see the [Sample-First Rule](windows-apis.instructions.md#sample-first-rule) for details and known pitfalls.
| # | Reference | When to consult |
|---|---|---|
| 19 | [Windows App SDK Samples](https://github.com/microsoft/WindowsAppSDK-Samples) | **Always search here first** before implementing any SDK API for the first time |
| 20 | [WinUI 3 Demos](https://github.com/microsoft/WinUI-Gallery) | Reference implementations and patterns |
| 21 | [Windows AI API Samples](https://github.com/microsoft/WindowsAppSDK-Samples/tree/main/Samples/WindowsAIFoundry/cs-winui) | AI API usage with WinUI (ImageDescription, TextRecognizer, LanguageModel, etc.) |