.NET desktop development with WPF and MVVM when the interface must support real work

This category explains WPF, XAML, and MVVM for teams that need desktop .NET software users can work in comfortably and developers can still change without breaking everything.

WPF is not dead: it is the right desktop choice when desktop is truly needed

Every year someone announces the death of WPF.

And every year thousands of Windows desktop applications continue to be developed and maintained with WPF, in contexts where the web is not the right answer and the desktop remains the most effective tool for the work they need to support.

WPF is not a nostalgic choice.

It is a deliberate choice when requirements include rich vector rendering, complex bindings on structured data models, local hardware integration, critical rendering performance, or simply users who need to work offline with applications that behave like applications, not like websites.

The question I always ask is not "why WPF instead of a web app?".

It is "which technology best supports the work the user needs to do?".

When the answer is Windows desktop, WPF remains the most mature, most performant, and best-integrated platform with the .NET ecosystem available today.

MVVM in WPF: why it works and where it breaks

MVVM is the reference pattern for WPF not for aesthetic reasons, but because it solves real problems: testability of presentation logic, separation of responsibilities between UI and domain, reusability of ViewModels across different views.

WPF's binding system is designed for MVVM: INotifyPropertyChanged, ObservableCollection, Command, and DataTemplate are built to connect ViewModels and Views without either knowing anything about the other.

When this works well, you can test all presentation logic without opening a window.

Where MVVM breaks down in WPF is when the View has complex behaviors that cannot be expressed with binding: animations, focus management, scroll, hardware interaction.

In these cases you use Behaviors (from Microsoft.Xaml.Behaviors), Attached Properties, or as a last resort, code-behind with strictly presentation logic.

Code-behind is not evil: it is only evil when it contains business logic.

ResponsibilityWhere it lives in MVVMCommon error
Business logicModel / Domain layerPutting it in the ViewModel
Presentation logicViewModelPutting it in code-behind
Layout and styleView (XAML)Hardcoded in code-behind
NavigationViewModel with serviceDirect dependency on Window

Performance in WPF: where it is lost and how to recover it

Slow WPF applications almost always have the same problem: too many elements in the visual tree, inefficient bindings, or missing virtualization on lists.

WPF's visual tree is the model the rendering system uses to build the interface.

Every control adds nodes.

A DataGrid with a thousand rows without virtualization creates thousands of controls in memory even if the user sees twenty.

VirtualizingStackPanel solves this problem by keeping only visible controls in memory.

Binding with Mode=TwoWay and UpdateSourceTrigger=PropertyChanged on fields that change frequently can cause continuous updates to the visual tree.

Evaluating OneWay where writing is not necessary is often sufficient to eliminate perceptible lag.

The reference tool for diagnosing performance problems in WPF is Snoop: it lets you inspect the live visual tree, see active bindings, identify unnecessary re-renders, and measure the cost of layout operations.

You do not optimize what you do not measure.

Migration from Windows Forms to WPF: when it is worth it and how to approach it

Migration from Windows Forms to WPF is not always the right move.

Before starting it is worth answering three questions: does the application genuinely need functionality that Windows Forms cannot offer?

Does the team have or can acquire the necessary XAML and MVVM skills?

Is the cost of migration justified by the value it produces?

If the answer to all three is yes, the best strategy is incremental migration with the WPF-Windows Forms interop pattern: WindowsFormsHost allows hosting Windows Forms controls inside a WPF window, and ElementHost does the reverse.

This allows migrating window by window without blocking the product.

The most critical part of migration is not technical: it is refactoring toward MVVM.

A Windows Forms application with business logic in the forms does not migrate to WPF simply by converting controls to XAML.

You migrate by first extracting logic from forms into testable classes, then connecting these classes to WPF ViewModels.

The typical cost of a poorly planned migration is double the estimate.

The reason is almost always that the existing code had no separation between UI and logic, and that separation must be built during the migration, not before and not after.

Analyses, cases, and articles on WPF, XAML, data binding, and MVVM

14 articles found

When WPF remains the right choice

WPF remains the right choice when you need rich, interactive desktop applications integrated into business workflows. In those scenarios interface quality, separation between UI and logic, and maintainable code directly affect the daily work of the people using the software.

Technologies related to desktop development

What is WPF

Discover what WPF is: Windows Presentation Foundation for developing modern desktop applications with XAML, C# and .NET.

Frequently asked questions

Yes, in enterprise contexts with legacy Windows applications and new internal desktop projects. WPF is the standard choice for LOB (Line of Business) applications on Windows when the interface is rich, performance requirements are high, and distribution is controlled. It is not the right choice for consumer cross-platform applications, where .NET MAUI or Blazor are more suitable.

MVVM, Model-View-ViewModel, separates UI logic (ViewModel) from visual representation (View) through data binding. In WPF it is fundamental because it makes code testable (the ViewModel does not depend on the View), enables parallel work between designers and developers, and reduces code-behind. INotifyPropertyChanged and ICommand are the basic building blocks of the implementation.

WPF is a Windows-only framework with a mature, stable, and well-documented programming model. .NET MAUI is cross-platform (iOS, Android, Windows, macOS) but with greater configuration complexity and less ecosystem maturity. For existing or new enterprise Windows applications, WPF remains the most solid choice. MAUI is preferable when the target includes mobile.

In modern WPF you use Microsoft.Extensions.DependencyInjection, the same container as ASP.NET Core. Services are registered in the container at application startup and injected into ViewModel constructors through a generic host (IHost). This approach makes WPF code consistent with the rest of the .NET ecosystem and facilitates code sharing with other layers.