Framework Desktop & UI v0.1.0

WinForms Expert

Create, modify, debug, or review Windows Forms applications only when the request contains a concrete Windows Forms marker. USE FOR: WinForms, Windows Forms, System.Windows.Forms, WinForms Form or UserControl designer files (*.Designer.cs or *.Designer.vb), Visual Studio WinForms Designer, TableLayoutPanel, BindingSource, DataGridView, Control.InvokeAsync, component-tray ownership, or custom control serialization. DO NOT USE FOR: WPF or WPF XAML, including Window.InputBindings, KeyBinding, commands, or DataContext; .NET MAUI; Avalonia; or any request where none of the listed Windows Forms markers is present.

Workflow

1. Establish the project constraints

  1. Inspect the solution/project, target framework, language, nullable setting, package management,

application startup, and existing build commands.

  1. Identify whether the app targets modern .NET or .NET Framework. Preserve its current family

unless migration is requested.

  1. Read the complete partial-file set and .resx for every affected Form/UserControl before

editing. Check base classes and nearby controls for repository conventions.

  1. If the defect is designer-specific, record the exact load/serialization error and determine

whether the problem occurs before making broad changes.

2. Plan the serialization boundary

  1. Classify each change as serialized UI state or runtime behavior.
  2. Put only designer-representable state in InitializeComponent.
  3. Put conditional setup, dynamic content, data loading, conversions, validation, and service

interaction in the main partial class or another runtime type.

  1. Prefer the smallest designer diff. Do not reorder or reformat the whole generated file.
  2. If editing generated code is avoidable, use the Designer or a runtime initialization method

instead. If direct editing is necessary, follow the existing generated shape exactly.

3. Implement the UI structure

For new or substantially revised layouts:

  • Prefer TableLayoutPanel, FlowLayoutPanel, SplitContainer, and nested UserControls over

brittle absolute positioning.

  • Divide complex screens into small layout regions. Avoid a single oversized grid.
  • Prefer AutoSize for caption/single-line rows and columns, Percent for expandable content,

and Absolute only for genuinely fixed-size content.

  • Preserve the existing form's AutoScaleMode. For new forms, choose scaling deliberately based

on the project conventions rather than copying coordinates from another DPI.

  • Ensure an autosized child container participates in the full sizing chain; a fixed-height

Panel or GroupBox inside an autosized row can still clip its contents.

  • Set meaningful minimum sizes where a resizable or localized dialog could otherwise become

unusable.

  • Keep localized UI text in the project's resources and allow labels/buttons to grow.

For dialogs:

  • Set AcceptButton, CancelButton, and appropriate DialogResult values.
  • Validate the form as a whole when submitting. Do not trap users in a field by canceling every

focus change.

  • Dispose modal forms according to the project's ownership pattern.

4. Add behavior outside generated code

  • Follow the project's language and style conventions; modern syntax belongs only in regular code.
  • Keep UI-thread affinity explicit. Marshal control access from background work.
  • A normal WinForms async void event handler resumes on its captured UI synchronization context

after await unless that context was deliberately bypassed. Direct control access there is valid. Use and await InvokeAsync when code can continue off-context, or when the task/repository contract explicitly requires a marshaled operation; do not rely on an unawaited post.

  • For modern .NET versions that support it, select the Control.InvokeAsync overload matching

whether the delegate is synchronous/asynchronous and whether it returns a value. Await the returned operation; do not create fire-and-forget UI work.

  • async void is acceptable for WinForms event handlers and overrides that must return void,

but catch exceptions around awaited work, handle cancellation intentionally, and surface unexpected failures through the application's established error path.

  • Do not use application-level exception hooks as a substitute for handling expected failures.

Application.ThreadException covers UI-thread exceptions; AppDomain.UnhandledException is primarily a last-chance logging path and does not make continued execution safe.

  • Preserve property allocation semantics. Do not change a cached property into

=> new ... or vice versa without confirming lifetime and disposal behavior.

For application-wide startup:

  • Preserve the current startup model. C# projects may configure application defaults in

Program.cs; VB projects normally use the VB Application Framework and ApplicationEvents.vb, not a newly invented Program.vb.

  • Use the APIs available to the actual TFM. Apply color mode or DPI defaults only when requested

or consistent with the app's existing policy.

  • Prefer SystemAware when maintaining the normal .NET WinForms DPI behavior. Use

PerMonitorV2 only when the application is designed and tested for per-monitor scaling.

5. Implement binding and serialization deliberately

For classic binding:

  • Use INotifyPropertyChanged for mutable bound objects and BindingList<T> or an established

adapter for list change notifications.

  • Use BindingSource as the designer/runtime mediator when that matches the existing design.
  • Put conversion logic in Binding.Format and Binding.Parse handlers rather than embedding

executable logic in designer code.

  • Treat one-way-to-source requests carefully: classic WinForms Binding does not provide a

direct WPF-style mode. Document and test any workaround instead of implying native support.

For modern WinForms MVVM APIs, first confirm the TFM contains the requested API:

  • Use Control.DataContext for ambient view-model context when available.
  • Use ButtonBase.Command, ToolStripItem.Command, and CommandParameter when available.
  • Keep view models in a UI-independent project when the solution already uses that separation or

the requested change benefits from it; do not add a new architecture for a small fix.

  • If design-time object data sources are required, preserve or add the project's established

.datasource and BindingSource pattern and verify it in the Designer.

For custom Component/Control properties, choose one intentional CodeDOM serialization policy:

| Policy | Mechanism | Use | |---|---|---| | Serialize only when non-default | [DefaultValue(...)] or matching ShouldSerializeX/ResetX | Stable values with a meaningful default | | Never serialize | [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] | Runtime-only, calculated, or unsupported state | | Serialize content | DesignerSerializationVisibility.Content plus designer-compatible mutable content | Owned nested objects/collections intentionally edited in the property grid |

Import System.ComponentModel (or fully qualify its attributes). Keep default metadata and runtime initialization directly aligned: for [DefaultValue(typeof(Color), "Yellow")], initialize the property or its backing field directly with Color.Yellow; do not hide the actual default behind a second constant or factory. Do not combine contradictory policies. Test property-grid editing and save/reload behavior for custom serialization changes.

6. Check usability and accessibility

  • Set logical TabIndex order and verify keyboard-only traversal.
  • Add unambiguous mnemonics where the product uses them.
  • Set meaningful accessible names/descriptions for actionable controls when labels or context do

not already provide them.

  • Verify default focus, accept/cancel behavior, resizing, clipping, and localized text growth.
  • Check at the DPI/theme combinations relevant to the change. System colors adapt to theme;

hard-coded colors and owner-drawn controls do not.

  • For owner drawing, DataGridView, icons, and custom painting, verify contrast in every supported

theme rather than assuming dark-mode adaptation.

7. Validate in increasing-cost order

  1. Re-read the designer diff and confirm every statement is serialization-safe and every referenced

field/handler exists in the correct partial class.

  1. Discover and run the repository's narrowest task-specific validation script or test when one is

present. A generic build does not replace a designer/layout/binding validator.

  1. Run the repository's smallest applicable restore/build/analyzer command. Use Visual Studio

MSBuild when the project type or .NET Framework dependencies require it.

  1. Run any remaining relevant automated tests.
  2. Launch the affected UI when possible and exercise creation, load, resize, keyboard navigation,

binding, async/error paths, and close/disposal behavior.

  1. When Visual Studio with a compatible WinForms Designer is available:

1. Open every changed Form/UserControl in the Designer. 2. Confirm the design surface, toolbox integration, property grid, component tray, and inherited controls load without errors. 3. Make a harmless reversible property change, save, close, reopen, and confirm the designer can serialize and reload the component. 4. Revert only the harmless validation change, not the requested implementation. 5. Build again after the serialization round trip.

Related skills

Framework Desktop & UI 1,820 tokens

Build cross-platform .NET applications with Uno Platform targeting WebAssembly, iOS, Android, macOS, Linux, and Windows from a single XAML/C# codebase.

Uno.WinUI.*
Framework Desktop & UI 3,074 tokens

Build and modernize WPF applications on .NET with correct XAML, data binding, commands, threading, styling, and Windows desktop migration decisions.

Microsoft.WindowsDesktop.App.WPF.*
Framework Desktop & UI 1,077 tokens

Build, maintain, or modernize Windows Forms applications with practical guidance on designer-driven UI, event handling, data binding, MVP separation, and migration to modern .NET.

Microsoft.WindowsDesktop.App.WindowsForms.*

Building AI agents on .NET?

Managed Code builds production AI agents in C# and .NET.