$npx -y skills add managedcode/dotnet-skills --skill winformsBuild, maintain, or modernize Windows Forms applications with practical guidance on designer-driven UI, event handling, data binding, MVP separation, and migration to modern .NET. USE FOR: working on Windows Forms UI, event-driven workflows, or classic LOB applications; migrating
| 1 | # Windows Forms |
| 2 | |
| 3 | ## Trigger On |
| 4 | |
| 5 | - working on Windows Forms UI, event-driven workflows, or classic LOB applications |
| 6 | - migrating WinForms from .NET Framework to modern .NET |
| 7 | - cleaning up oversized form code or designer coupling |
| 8 | - implementing data binding, validation, or control customization |
| 9 | |
| 10 | ## Workflow |
| 11 | |
| 12 | 1. **Respect designer boundaries** — never edit `.Designer.cs` directly; changes are lost on regeneration. |
| 13 | 2. **Separate business logic from forms** — use MVP (Model-View-Presenter) pattern. Forms orchestrate UI; presenters contain logic; services handle data access. |
| 14 | ```csharp |
| 15 | // View interface — forms implement this |
| 16 | public interface ICustomerView |
| 17 | { |
| 18 | string CustomerName { get; set; } |
| 19 | event EventHandler SaveRequested; |
| 20 | void ShowError(string message); |
| 21 | } |
| 22 | |
| 23 | // Presenter — testable without UI |
| 24 | public class CustomerPresenter |
| 25 | { |
| 26 | private readonly ICustomerView _view; |
| 27 | private readonly ICustomerService _service; |
| 28 | public CustomerPresenter(ICustomerView view, ICustomerService service) |
| 29 | { |
| 30 | _view = view; |
| 31 | _service = service; |
| 32 | _view.SaveRequested += async (s, e) => |
| 33 | { |
| 34 | try { await _service.SaveAsync(_view.CustomerName); } |
| 35 | catch (Exception ex) { _view.ShowError(ex.Message); } |
| 36 | }; |
| 37 | } |
| 38 | } |
| 39 | ``` |
| 40 | 3. **Use DI from Program.cs** (.NET 6+): |
| 41 | ```csharp |
| 42 | var services = new ServiceCollection(); |
| 43 | services.AddSingleton<ICustomerService, CustomerService>(); |
| 44 | services.AddTransient<MainForm>(); |
| 45 | using var sp = services.BuildServiceProvider(); |
| 46 | Application.Run(sp.GetRequiredService<MainForm>()); |
| 47 | ``` |
| 48 | 4. **Use data binding** via `BindingSource` and `INotifyPropertyChanged` instead of manual control population. See [references/patterns.md](references/patterns.md) for complete binding patterns. |
| 49 | 5. **Use async/await** for I/O operations — disable controls during loading, use `Progress<T>` for progress reporting. Never block the UI thread. |
| 50 | 6. **Validate with `ErrorProvider`** and the `Validating` event. Call `ValidateChildren()` before save operations. |
| 51 | 7. **Modernize incrementally** — prefer better structure over big-bang rewrites. Use .NET 8+ features (button commands, stock icons) when available. |
| 52 | |
| 53 | ## Current Upstream Notes |
| 54 | |
| 55 | - The July 2026 Windows Forms overview refresh remains focused on Windows desktop, designer-driven controls, events, data binding, and migration to modern .NET. It does not change the framework-selection guidance: improve form boundaries and designer safety before proposing a rewrite. |
| 56 | - For docs-driven updates, validate whether the app targets .NET Framework, modern .NET, or mixed libraries before changing project format, designer files, or deployment assumptions. |
| 57 | |
| 58 | ```mermaid |
| 59 | flowchart LR |
| 60 | A["Form event"] --> B["Presenter handles logic"] |
| 61 | B --> C["Service layer / data access"] |
| 62 | C --> D["Update view via interface"] |
| 63 | D --> E["Validate and display results"] |
| 64 | ``` |
| 65 | |
| 66 | ## Key Decisions |
| 67 | |
| 68 | | Decision | Guidance | |
| 69 | |----------|----------| |
| 70 | | MVP vs MVVM | Prefer MVP for WinForms — simpler with event-driven model | |
| 71 | | BindingSource vs manual | Always prefer BindingSource for list/detail binding | |
| 72 | | Sync vs async I/O | Always async — use `async void` only for event handlers | |
| 73 | | Custom controls | Extract reusable `UserControl` when form grows beyond ~300 lines | |
| 74 | | .NET Framework → .NET | Use the official migration guide; validate designer compatibility first | |
| 75 | |
| 76 | ## Deliver |
| 77 | |
| 78 | - less brittle form code with clear UI/logic separation |
| 79 | - MVP pattern with testable presenters |
| 80 | - pragmatic modernization guidance for WinForms-heavy apps |
| 81 | - data binding and validation patterns that reduce manual wiring |
| 82 | |
| 83 | ## Validate |
| 84 | |
| 85 | - designer files stay stable and are not hand-edited |
| 86 | - forms are not acting as the application service layer |
| 87 | - async operations do not block the UI thread |
| 88 | - validation is implemented consistently with ErrorProvider |
| 89 | - Windows-only runtime behavior is tested on target |
| 90 | |
| 91 | ## References |
| 92 | |
| 93 | - [references/patterns.md](references/patterns.md) - WinForms architectural patterns (MVP, MVVM, Passive View), data binding, validation, form communication, threading, DI setup, and .NET 8+ features |
| 94 | - [references/migration.md](references/migration.md) - step-by-step migration from .NET Framework to modern |