Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Windows Forms and WinUI 3 are both .NET desktop UI frameworks, but they use different layout, binding, windowing, and application models. Use this article to translate familiar patterns when you build a new WinUI 3 screen or plan a migration.
You don't need to rewrite a working Windows Forms app solely to adopt a newer UI framework. Compare the business value, accessibility requirements, deployment constraints, test coverage, and lifetime of the existing app. You can also adopt supported non-XAML Windows App SDK capabilities without migrating every screen.
Tip
Use Plan your modernization with an AI assistant to have an AI coding assistant inspect your solution and draft an incremental plan grounded in the migration guidance.
Understand the main differences
- UI definition: Windows Forms commonly uses generated designer code. WinUI 3 defines the visual tree in XAML and connects it to C#.
- Layout: Windows Forms often uses coordinates, anchoring, docking, and layout panels. WinUI layouts are usually composed with
Grid,StackPanel, and other XAML panels. - Binding: WinUI supports declarative
x:BindandBinding. You can use code-behind for simple UI coordination or adopt MVVM incrementally. - Application model: A WinUI 3 app uses
Application,Window, pages, and the Windows App SDK lifecycle and deployment model. - Rendering and theming: WinUI controls use Fluent Design resources and respond to Windows themes, text scale, and input modes.
Map common controls and patterns
The mappings below are starting points, not automated substitutions. Re-evaluate the workflow and accessibility behavior instead of recreating the old visual tree control for control.
| Windows Forms | WinUI 3 starting point | Notes |
|---|---|---|
Form |
Window |
A Window hosts XAML content and isn't a control in the page's visual tree. |
Panel with absolute positioning |
Grid, StackPanel, or another adaptive panel |
Use Canvas only when absolute coordinates are intrinsic to the scenario. |
FlowLayoutPanel |
StackPanel or a wrapping layout |
Choose based on whether items must wrap. |
TableLayoutPanel |
Grid |
Use row and column definitions with fixed, automatic, or proportional sizing. |
DataGridView |
No first-party equivalent | Use a list control for simple records or evaluate a supported third-party grid for full grid behavior. Don't use the older UWP Community Toolkit DataGrid. |
ListBox |
ListView or ItemsView |
Both display selectable collections; compare their interaction and layout models. |
Label |
TextBlock |
Use an associated header or accessible name for form fields. |
TextBox, ComboBox, Button, CheckBox, RadioButton |
Controls with the same names | APIs and styling differ even when names match. |
MenuStrip |
MenuBar |
Use MenuFlyout for contextual menus. |
StatusStrip |
A status area composed with layout controls | Use InfoBar for important, actionable status messages rather than as a permanent status strip. |
TabControl |
TabView |
Useful for multiple open records or documents. |
ToolTip |
ToolTipService |
Don't put essential information only in a tooltip. |
BindingSource |
A view model, collection, and XAML binding | ObservableCollection<T> reports collection changes; item properties need their own change notification. |
ErrorProvider |
App-defined validation presentation | WinUI 3 doesn't provide a complete equivalent. See Build a validated form. |
BackgroundWorker |
Asynchronous I/O or Task.Run for CPU-bound work |
async doesn't move CPU work off the UI thread. Marshal UI updates through DispatcherQueue only when execution is on another thread. |
MessageBox.Show |
ContentDialog |
Set the dialog's XamlRoot before showing it. |
OpenFileDialog and SaveFileDialog |
Windows App SDK or Windows Runtime picker APIs | Follow the current desktop picker guidance; some APIs require a window identifier or HWND initialization. |
NotifyIcon |
Win32 notification-area integration or a supported library | Windows App SDK doesn't include a first-party tray-icon control. |
ProgressBar |
ProgressBar or ProgressRing |
Prefer determinate progress when the app can calculate completion. |
DateTimePicker |
DatePicker and TimePicker |
Compose them when the workflow needs both values. |
NumericUpDown |
NumberBox |
Configure validation and acceptable ranges for the business rule. |
SplitContainer |
A resizable layout implementation | A Grid supplies layout, but it doesn't by itself provide a draggable splitter. |
WebBrowser |
WebView2 |
Review initialization, navigation, origin, and message-handling security. |
Translate startup and navigation
The generated WinUI 3 project provides the application entry point and creates an App instance. App.OnLaunched typically creates and activates the first Window.
A page or control can load data from its Loaded event, a navigation callback, or an explicit initialization command. Avoid starting fallible asynchronous work in a view-model constructor, because a constructor can't be awaited or report failure cleanly.
Use:
Framenavigation for page-based experiences.ContentDialogfor short modal interactions within a window.- Additional
Windowinstances for independent top-level views.
See App lifecycle, Multiple windows, and Dialogs and flyouts.
Translate data binding
Windows Forms code often assigns control properties or configures a BindingSource. WinUI can declare the relationship in XAML:
| Scenario | Windows Forms | WinUI 3 |
|---|---|---|
| Display a property | nameLabel.Text = customer.Name; |
<TextBlock Text="{x:Bind ViewModel.Customer.Name, Mode=OneWay}" /> |
| Edit a property | DataBindings.Add(...) |
<TextBox Text="{x:Bind ViewModel.Name, Mode=TwoWay}" /> |
| Display a collection | Set DataSource |
Bind ItemsSource to a collection |
| Report changes | INotifyPropertyChanged or reset bindings |
INotifyPropertyChanged on the bound object |
Set an explicit x:Bind mode. The default is OneTime, which doesn't update when a property changes.
MVVM is useful when a screen has substantial state, commands, or testable business behavior, but it isn't mandatory. Keep business and data-access logic out of the visual layer regardless of whether you use a toolkit.
Plan an incremental migration
- Identify a bounded workflow with clear value and dependencies.
- Separate business and data-access logic from Windows Forms controls.
- Add automated tests around that logic and the data contract.
- Rebuild the workflow with WinUI layout and interaction patterns rather than copying coordinates.
- Test accessibility, text scaling, theming, deployment, and failure recovery.
- Decide how old and new components communicate during the transition.
Related content
Windows developer