What WPF is and how a project is structured
WPF on modern .NET versus .NET Framework, App.xaml and startup, the visual tree, and a project layout that keeps XAML and logic apart.
What WPF actually is
WPF is a retained-mode UI framework: you describe a tree of objects, and the framework keeps it painted. That is the key difference from WinForms, where you own the drawing and the state. It also explains why layout, styling and animation are declarative here and manual there.
| Aspect | WPF | WinForms |
|---|---|---|
| Rendering | Retained mode, vector based, DirectX backed | Immediate mode, GDI+ drawing |
| UI definition | XAML, a serialised object graph | Designer-generated code |
| Layout | Measure and arrange passes, panels | Dock, Anchor, absolute coordinates |
| Styling | Styles, templates, resource dictionaries | Per-control properties and owner-draw |
| Scaling | Resolution independent by design | DPI awareness plus manual scaling |
| Data flow | Binding and change notification | Manual assignment and event handlers |
Use WPF on .NET 8 or later. WPF on .NET Framework 4.8 still runs, but it misses the performance work, the modern C# language level and the smaller hosting story. The API is nearly identical, which makes the upgrade mostly a project-file change.
App.xaml, startup and the project layout
<!-- App.xaml: application-wide resources and the startup URI -->
<Application x:Class="Orders.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Colors.xaml" />
<ResourceDictionary Source="Themes/Controls.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>// App.xaml.cs - keep real startup work here instead of StartupUri when it grows
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
DispatcherUnhandledException += (s, args) =>
{
Log.Fatal(args.Exception, "Unhandled UI exception");
MessageBox.Show("Something went wrong. The details were logged.");
args.Handled = true; // keep the app alive; remove if you prefer to crash
};
var services = new ServiceCollection();
services.AddSingleton<OrderRepository>();
services.AddTransient<MainViewModel>();
var window = new MainWindow { DataContext = services.BuildServiceProvider().GetRequiredService<MainViewModel>() };
window.Show();
}
}App.xamlcompiles intoApp.g.cs; theMainmethod that the entry point uses is generated, not written by you.- Remove
StartupUrithe moment you need dependency injection or any pre-window work, or you will build the window twice. - A conventional layout is
Views/,ViewModels/,Models/,Services/,Themes/. It is not a framework requirement, but it keeps the resource dictionaries findable.
The visual tree and code-behind
<Window x:Class="Orders.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Orders" Height="600" Width="900">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Header}" />
<DataGrid Grid.Row="1" ItemsSource="{Binding Orders}" />
</Grid>
</Window>// MainWindow.xaml.cs - the code-behind: only view concerns belong here
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); // required: builds the XAML tree
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
// wiring a view-only concern is fine here
FocusManager.SetFocusedElement(this, SearchBox);
}
}The visual tree is every rendered element, including the ones a template created; the logical tree is only what you declared. Resource lookup, event routing and ItemsControl containers follow the logical tree, while hit testing and rendering follow the visual tree - most confusing WPF behaviour is one of these two being the one you did not mean.
FAQ
Is XAML required?
How long does the XAML parse cost at startup?
Related
XAML and layout panels Dependency properties and routed events
Last refreshed 2026-09-18.