Skip to content
WPF and Windows Forms — Desktop UI Development Explained

WPF and Windows Forms — Desktop UI Development Explained

DodaTech Updated Jun 15, 2026 5 min read

WPF (Windows Presentation Foundation) and Windows Forms are Microsoft’s two desktop UI frameworks for building Windows applications. WPF uses XAML and hardware acceleration; WinForms uses a visual designer with lightweight controls.

What You’ll Learn

You’ll master WPF’s XAML, data binding, and MVVM architecture, plus WinForms’ designer and control system. You’ll build a WPF form with MVVM and learn when to choose each framework.

Why WPF and WinForms Matter

Despite the rise of web and mobile, Windows desktop apps power critical business workflows — enterprise CRMs, financial trading platforms, medical imaging, and engineering tools. At DodaTech, Durga Antivirus Pro uses WPF for its desktop interface, leveraging hardware-accelerated rendering for real-time threat visualizations.

WPF and WinForms Learning Path

    flowchart LR
  A[Visual Studio] --> B[WPF & WinForms]
  B --> C{You Are Here}
  C --> D[Identity & Auth]
  C --> E[.NET MAUI]
  style C fill:#f90,color:#fff
  

WPF: XAML and Data Binding

WPF separates UI (XAML) from logic (C#). XAML defines the visual tree, and data binding connects it to data:

<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Customer Editor" Height="300" Width="400">

    <Grid Margin="20" VerticalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0" Text="Name:" Margin="5" />
        <TextBox Grid.Row="0" Grid.Column="1"
                 Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Margin="5" />

        <TextBlock Grid.Row="1" Grid.Column="0" Text="Email:" Margin="5" />
        <TextBox Grid.Row="1" Grid.Column="1"
                 Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" Margin="5" />

        <TextBlock Grid.Row="2" Grid.Column="0" Text="Phone:" Margin="5" />
        <TextBox Grid.Row="2" Grid.Column="1"
                 Text="{Binding Phone}" Margin="5" />

        <StackPanel Grid.Row="3" Grid.Column="1" Orientation="Horizontal" Margin="5">
            <Button Content="Save" Command="{Binding SaveCommand}"
                    Width="80" Height="30" Margin="5" />
            <Button Content="Cancel" Command="{Binding CancelCommand}"
                    Width="80" Height="30" Margin="5" />
        </StackPanel>

        <!-- Validation summary -->
        <ItemsControl Grid.Row="4" Grid.Column="1"
                      ItemsSource="{Binding Errors}" Foreground="Red" />
    </Grid>
</Window>

WPF MVVM with CommunityToolkit.Mvvm

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Collections.ObjectModel;

public partial class CustomerViewModel : ObservableObject
{
    [ObservableProperty]
    private string name;

    [ObservableProperty]
    private string email;

    [ObservableProperty]
    private string phone;

    public ObservableCollection<string> Errors { get; } = new();

    [RelayCommand]
    async Task Save()
    {
        Errors.Clear();

        if (string.IsNullOrWhiteSpace(Name))
            Errors.Add("Name is required.");
        if (string.IsNullOrWhiteSpace(Email) || !Email.Contains("@"))
            Errors.Add("Valid email is required.");

        if (Errors.Count > 0) return;

        // Save to database
        var customer = new Customer { Name = Name, Email = Email, Phone = Phone };
        await CustomerService.SaveAsync(customer);

        // Clear form
        Name = Email = Phone = string.Empty;
    }

    [RelayCommand]
    void Cancel()
    {
        Name = Email = Phone = string.Empty;
        Errors.Clear();
    }
}

Windows Forms: Designer and Controls

WinForms uses a drag-and-drop designer. The same form in WinForms:

// Form1.cs
public partial class Form1 : Form
{
    private TextBox txtName;
    private TextBox txtEmail;
    private Button btnSave;
    private Label lblStatus;
    private ListBox lstCustomers;
    private BindingSource customerSource;

    public Form1()
    {
        InitializeComponent();   // Generated by designer
        LoadCustomers();
    }

    private void LoadCustomers()
    {
        customerSource.DataSource = CustomerService.GetAll();
        lstCustomers.DisplayMember = "Name";
        lstCustomers.DataSource = customerSource;
    }

    private void btnSave_Click(object sender, EventArgs e)
    {
        var customer = new Customer
        {
            Name = txtName.Text,
            Email = txtEmail.Text
        };
        CustomerService.Save(customer);
        LoadCustomers();
        lblStatus.Text = "Customer saved!";
    }
}

When to Use WPF vs WinForms

FactorWPFWinForms
UI complexityRich, animated, custom controlsStandard Windows controls
PerformanceHardware-accelerated (GPU)Lightweight (CPU)
Data bindingPowerful, declarative (XAML)Basic, event-driven
Learning curveSteeper (XAML, MVVM)Gentle (designer)
Modern featuresStyles, templates, animationsNone (legacy)
Best forModern apps, data-heavy UIsInternal tools, simple forms

Choose WPF for modern desktop apps with rich UI, complex data binding, and custom styling. Choose WinForms for rapid development of form-based internal tools where a modern look isn’t critical.

Common Mistakes Beginners Make

1. Mixing UI Logic in Code-Behind (WPF)

WPF’s code-behind should be minimal. Business logic belongs in ViewModels. Violating this makes testing and maintenance harder.

2. Forgetting INotifyPropertyChanged

Without it, the UI never updates when data changes. Use CommunityToolkit.Mvvm’s [ObservableProperty] to avoid boilerplate.

3. Using WinForms Drag-and-Drop for Complex Layouts

Nested panels and anchors produce brittle layouts. Use TableLayoutPanel or switch to WPF for complex UIs.

4. Not Disposing Resources

WinForms controls implement IDisposable. Use using blocks or ensure proper disposal to avoid memory leaks.

5. Ignoring Threading

UI updates must happen on the main thread. Use Control.Invoke() (WinForms) or Dispatcher.Invoke() (WPF) for cross-thread updates.

6. Hardcoding Sizes and Positions

WinForms forms designed at 1920×1080 break on smaller screens. Use Dock and Anchor properties for resizability.

7. Not Using Command Pattern in WPF

Button click handlers violate MVVM. Use ICommand (via [RelayCommand]) for clean separation.

Practice Questions

1. What is the main difference between WPF and WinForms rendering?

WPF uses DirectX (hardware-accelerated). WinForms uses GDI+ (CPU-based).

2. What is the MVVM pattern and why use it in WPF?

MVVM separates View (XAML), ViewModel (logic), and Model (data). It enables unit testing, designer collaboration, and cleaner code.

3. What does {Binding Name} do in XAML?

It binds the control’s property to the Name property of the current DataContext (usually the ViewModel).

4. When would you choose WinForms over WPF?

For simple internal tools, legacy maintenance, or when rapid development with the visual designer is more important than modern UI.

5. Challenge: Add validation highlighting.

In the WPF form, change the TextBox border to red when validation fails. Use Validation.ErrorTemplate and INotifyDataErrorInfo.

Mini Project: Customer Manager

Build a WPF customer management app:

  1. CustomerViewModel with Name, Email, Phone (using [ObservableProperty])
  2. Save and Cancel commands with validation
  3. ListBox bound to a collection of customers
  4. When a customer is selected, fields populate for editing
  5. Delete button with confirmation dialog

FAQ

Is WPF still supported?
Yes. WPF is part of .NET (Windows-only) and fully supported. It will not receive new features but continues to get security updates.
Can WinForms and WPF coexist in the same app?
Yes. You can host WinForms controls in WPF with WindowsFormsHost and vice versa with ElementHost.
Does WPF support .NET Core/.NET 5+?
Yes. WPF and WinForms have been available since .NET Core 3.0.

What’s Next

Congratulations on completing this WPF and WinForms tutorial! Here’s where to go from here:

  • Practice daily — Build one small form per day
  • Build a project — Create a full CRUD desktop app
  • Explore related topics — Custom WPF controls, WinForms interop
  • Join the community — Share your desktop apps and get feedback

Remember: every expert was once a beginner. Keep building!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro