Skip to Content
Nextra 4.0 is released 🎉

WPF Windows Presentation Foundation

WPF (Windows Presentation Foundation) 是微软推出的用于创建桌面应用程序的框架,它是 .NET Framework 的一部分,提供了强大的图形、动画和用户界面功能。

核心特性

  • XAML 声明式 UI:使用 XAML 标记语言创建用户界面
  • 数据绑定:强大的数据绑定机制,支持双向绑定
  • MVVM 模式:支持 Model-View-ViewModel 架构模式
  • 丰富的控件库:提供大量内置控件和自定义控件支持
  • 矢量图形:支持矢量图形和动画
  • 主题和样式:灵活的样式和主题系统
  • 多线程支持:支持多线程应用程序开发

系统要求

  • Windows 7 或更高版本
  • .NET Framework 3.5 或更高版本
  • Visual Studio 2019/2022 或 Visual Studio Code
  • Windows SDK

安装与配置

安装 .NET Framework

# 下载并安装 .NET Framework # 访问 https://dotnet.microsoft.com/download

创建 WPF 项目

# 使用 Visual Studio # 1. 文件 -> 新建 -> 项目 # 2. 选择 "WPF 应用程序" 模板 # 3. 配置项目名称和位置 # 或使用命令行 dotnet new wpf -n MyWpfApp

项目结构

MyWpfApp/ ├── App.xaml # 应用程序定义 ├── App.xaml.cs # 应用程序代码 ├── MainWindow.xaml # 主窗口 UI ├── MainWindow.xaml.cs # 主窗口代码 ├── Properties/ │ └── AssemblyInfo.cs # 程序集信息 ├── Models/ # 数据模型 ├── ViewModels/ # 视图模型 ├── Views/ # 视图 └── Resources/ # 资源文件 ├── Images/ ├── Styles/ └── Themes/

基础使用

创建主窗口

<!-- MainWindow.xaml --> <Window x:Class="MyWpfApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="450" Width="800"> <Grid> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="Hello, WPF!" FontSize="24" HorizontalAlignment="Center"/> <Button x:Name="myButton" Content="Click me" Click="myButton_Click" Margin="0,10,0,0"/> </StackPanel> </Grid> </Window>
// MainWindow.xaml.cs using System.Windows; namespace MyWpfApp { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void myButton_Click(object sender, RoutedEventArgs e) { myButton.Content = "Clicked!"; } } }

应用程序入口

// App.xaml.cs using System.Windows; namespace MyWpfApp { public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); MainWindow mainWindow = new MainWindow(); mainWindow.Show(); } } }

UI 控件

基础控件

<!-- 按钮 --> <Button Content="Primary Button" Background="Blue" Foreground="White" Padding="10,5"/> <!-- 文本框 --> <TextBox Text="Enter text here" Width="200" Height="25"/> <!-- 标签 --> <Label Content="This is a label" FontSize="14" FontWeight="Bold"/> <!-- 复选框 --> <CheckBox Content="I agree to the terms" IsChecked="True"/> <!-- 单选按钮 --> <StackPanel Orientation="Horizontal"> <RadioButton Content="Option 1" GroupName="Options" IsChecked="True"/> <RadioButton Content="Option 2" GroupName="Options"/> </StackPanel>

布局控件

<!-- 网格布局 --> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="2*"/> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Text="Header"/> <TextBlock Grid.Row="0" Grid.Column="1" Text="Content"/> <TextBlock Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Text="Footer"/> </Grid> <!-- 堆叠面板 --> <StackPanel Orientation="Vertical" Margin="10"> <Button Content="Button 1" Margin="0,5"/> <Button Content="Button 2" Margin="0,5"/> <Button Content="Button 3" Margin="0,5"/> </StackPanel> <!-- 停靠面板 --> <DockPanel> <Button DockPanel.Dock="Top" Content="Top"/> <Button DockPanel.Dock="Left" Content="Left"/> <Button DockPanel.Dock="Right" Content="Right"/> <Button Content="Fill"/> </DockPanel>

容器控件

<!-- 选项卡控件 --> <TabControl> <TabItem Header="Tab 1"> <TextBlock Text="Content for Tab 1"/> </TabItem> <TabItem Header="Tab 2"> <TextBlock Text="Content for Tab 2"/> </TabItem> </TabControl> <!-- 列表视图 --> <ListView> <ListViewItem Content="Item 1"/> <ListViewItem Content="Item 2"/> <ListViewItem Content="Item 3"/> </ListViewView> <!-- 树视图 --> <TreeView> <TreeViewItem Header="Root"> <TreeViewItem Header="Child 1"/> <TreeViewItem Header="Child 2"/> </TreeViewItem> </TreeView>

数据绑定

简单绑定

<StackPanel> <TextBox x:Name="InputTextBox" Text="{Binding InputText, UpdateSourceTrigger=PropertyChanged}"/> <TextBlock Text="{Binding InputText}"/> </StackPanel>
public class MainViewModel : INotifyPropertyChanged { private string _inputText; public string InputText { get => _inputText; set { _inputText = value; OnPropertyChanged(nameof(InputText)); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

集合绑定

<ListView ItemsSource="{Binding Items}"> <ListView.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}" Width="100"/> <TextBlock Text="{Binding Description}"/> </StackPanel> </DataTemplate> </ListView.ItemTemplate> </ListView>
public class MainViewModel : INotifyPropertyChanged { private ObservableCollection<Item> _items; public ObservableCollection<Item> Items { get => _items; set { _items = value; OnPropertyChanged(nameof(Items)); } } public MainViewModel() { Items = new ObservableCollection<Item> { new Item { Name = "Item 1", Description = "Description 1" }, new Item { Name = "Item 2", Description = "Description 2" } }; } }

MVVM 模式

Model

public class User { public string Name { get; set; } public string Email { get; set; } public int Age { get; set; } }

ViewModel

public class UserViewModel : INotifyPropertyChanged { private User _user; private ICommand _saveCommand; public User User { get => _user; set { _user = value; OnPropertyChanged(nameof(User)); } } public ICommand SaveCommand { get => _saveCommand ??= new RelayCommand(Save); } private void Save() { // 保存用户数据 MessageBox.Show("User saved!"); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

View

<Window x:Class="MyWpfApp.UserWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="User Management" Height="300" Width="400"> <Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Content="Name:"/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding User.Name, UpdateSourceTrigger=PropertyChanged}"/> <Label Grid.Row="1" Grid.Column="0" Content="Email:"/> <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding User.Email, UpdateSourceTrigger=PropertyChanged}"/> <Label Grid.Row="2" Grid.Column="0" Content="Age:"/> <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding User.Age, UpdateSourceTrigger=PropertyChanged}"/> <Button Grid.Row="3" Grid.Column="1" Content="Save" Command="{Binding SaveCommand}" HorizontalAlignment="Right"/> </Grid> </Window>

样式和主题

定义样式

<Window.Resources> <Style x:Key="CustomButtonStyle" TargetType="Button"> <Setter Property="Background" Value="#FF007ACC"/> <Setter Property="Foreground" Value="White"/> <Setter Property="Padding" Value="15,8"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border Background="{TemplateBinding Background}" CornerRadius="4"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#FF005A9E"/> </Trigger> </Style.Triggers> </Style> </Window.Resources>

使用样式

<Button Style="{StaticResource CustomButtonStyle}" Content="Custom Button"/>

命令绑定

public class RelayCommand : ICommand { private readonly Action<object> _execute; private readonly Func<object, bool> _canExecute; public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public bool CanExecute(object parameter) { return _canExecute == null || _canExecute(parameter); } public void Execute(object parameter) { _execute(parameter); } }

异步编程

public class AsyncViewModel : INotifyPropertyChanged { private ObservableCollection<string> _items; private ICommand _loadDataCommand; public ObservableCollection<string> Items { get => _items; set { _items = value; OnPropertyChanged(nameof(Items)); } } public ICommand LoadDataCommand { get => _loadDataCommand ??= new RelayCommand(async _ => await LoadDataAsync()); } private async Task LoadDataAsync() { try { // 模拟异步加载数据 await Task.Delay(2000); Items = new ObservableCollection<string> { "Item 1", "Item 2", "Item 3" }; } catch (Exception ex) { MessageBox.Show($"Error: {ex.Message}"); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }

资源管理

应用程序资源

<!-- App.xaml --> <Application x:Class="MyWpfApp.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml"> <Application.Resources> <SolidColorBrush x:Key="PrimaryBrush" Color="#FF007ACC"/> <SolidColorBrush x:Key="SecondaryBrush" Color="#FF6C757D"/> </Application.Resources> </Application>

使用资源

<Button Background="{StaticResource PrimaryBrush}" Content="Primary Button"/>

最佳实践

性能优化

  1. 虚拟化:使用 VirtualizingStackPanel 处理大量数据
  2. 延迟加载:使用 x:DeferLoadStrategy="Lazy"
  3. 避免频繁的 UI 更新:使用 Dispatcher.BeginInvoke
  4. 合理使用绑定:避免不必要的双向绑定

代码组织

  1. MVVM 模式:分离关注点,提高可维护性
  2. 命令模式:使用 ICommand 处理用户交互
  3. 依赖注入:使用 IoC 容器管理依赖
  4. 单元测试:为 ViewModel 编写单元测试

常见问题

Q: 如何处理长时间运行的操作?

A: 使用异步编程和后台线程,避免阻塞 UI 线程。

Q: 如何实现数据验证?

A: 使用 IDataErrorInfoINotifyDataErrorInfo 接口。

Q: 如何处理异常?

A: 使用全局异常处理器和 try-catch 块。

学习资源

相关技术

  • WinUI - 现代 Windows UI 框架
  • XAML - 用户界面标记语言
  • C# - 编程语言
  • MVVM - 架构模式
最近更新:12/9/2025, 2:17:56 AM