WPF 开发指南
构建现代桌面应用程序的完整指南
什么是 WPF?
WPF (Windows Presentation Foundation) 是微软推出的用于构建 Windows 桌面应用程序的 UI 框架。它提供了强大的图形渲染能力、丰富的控件库、灵活的布局系统和数据绑定机制,使开发者能够创建美观、高性能的桌面应用。
声明式 UI
使用 XAML 声明式语言构建用户界面,实现设计与逻辑的分离
数据绑定
强大的数据绑定系统,实现 UI 与数据的自动同步
样式与模板
灵活的样式和模板系统,完全自定义控件外观
高性能
基于 DirectX 的渲染引擎,提供流畅的图形体验
动画与媒体
内置动画系统和媒体支持,创建丰富的交互体验
可扩展性
支持自定义控件和行为,满足各种业务需求
💡 为什么选择 WPF?
WPF 是构建企业级桌面应用的理想选择。它提供了完整的开发框架,从基础的 UI 控件到高级的图形渲染,从数据绑定到 MVVM 架构,应有尽有。无论是简单的工具应用还是复杂的业务系统,WPF 都能胜任。
安装环境
开始 WPF 开发之前,需要准备以下开发环境:
安装 Visual Studio
下载并安装 Visual Studio 2022,选择 ".NET 桌面开发" 工作负载。
# 通过命令行安装 Visual Studio Build Tools
winget install Microsoft.VisualStudio.2022.BuildTools --override "--wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools"
安装 .NET SDK
安装最新的 .NET SDK(推荐 .NET 8 或更高版本)。
# 检查已安装的 .NET 版本
dotnet --version
# 安装 .NET 8 SDK
winget install Microsoft.DotNet.SDK.8
安装 WPF 扩展
在 Visual Studio 中安装 XAML 设计器和 WPF 相关扩展。
⚠️ 系统要求
- 操作系统:Windows 10 或更高版本
- 开发工具:Visual Studio 2022 或 Visual Studio Code
- .NET SDK:.NET 6.0 或更高版本
- 内存:至少 8GB RAM(推荐 16GB)
第一个 WPF 项目
让我们创建一个简单的 WPF 应用程序,了解基本的项目结构。
# 使用 .NET CLI 创建 WPF 项目
dotnet new wpf -n MyFirstWpfApp
cd MyFirstWpfApp
# 运行项目
dotnet run
项目结构
MyFirstWpfApp/
├── App.xaml # 应用程序定义
├── App.xaml.cs # 应用程序代码
├── AssemblyInfo.cs # 程序集信息
├── MainWindow.xaml # 主窗口 UI 定义
├── MainWindow.xaml.cs # 主窗口代码
└── MyFirstWpfApp.csproj # 项目文件
MainWindow.xaml 示例
<Window x:Class="MyFirstWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="我的第一个 WPF 应用" Height="450" Width="800">
<Grid>
<StackPanel Margin="20" VerticalAlignment="Center">
<TextBlock Text="欢迎使用 WPF!"
FontSize="32"
FontWeight="Bold"
HorizontalAlignment="Center"
Margin="0,0,0,20"/>
<Button Content="点击我"
Width="150"
Height="40"
HorizontalAlignment="Center"
Click="Button_Click"/>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs 示例
using System.Windows;
namespace MyFirstWpfApp
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello, WPF!");
}
}
}
XAML 基础
XAML (Extensible Application Markup Language) 是一种声明式标记语言,用于定义 WPF 应用程序的用户界面。
XAML 语法基础
<!-- 基本元素语法 -->
<Button Content="按钮" Width="100" Height="30" />
<!-- 属性元素语法 -->
<Button Width="100" Height="30">
<Button.Content>
按钮
</Button.Content>
</Button>
<!-- 内容属性 -->
<Button Width="100" Height="30">
按钮
</Button>
<!-- 附加属性 -->
<Grid>
<Button Grid.Row="0" Grid.Column="0" Content="按钮" />
</Grid>
命名空间
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace">
<!-- 使用 x: 命名空间 -->
<Button x:Name="myButton" x:FieldModifier="public" />
<!-- 使用自定义命名空间 -->
<local:CustomControl />
</Window>
标记扩展
<!-- 静态资源 -->
<Button Content="{StaticResource ButtonText}" />
<!-- 动态资源 -->
<Button Background="{DynamicResource ButtonBackground}" />
<!-- 绑定 -->
<TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged}" />
<!-- 相对源 -->
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=Title}" />
<!-- 模板绑定 -->
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" />
</ControlTemplate>
💡 XAML 最佳实践
- 使用合理的命名约定,保持代码可读性
- 将复杂样式提取到资源字典中
- 使用标记扩展简化代码
- 合理使用 x:Name,只在需要代码访问时命名
- 保持 XAML 文件简洁,避免过度嵌套
应用模型
WPF 应用程序模型定义了应用程序的生命周期、启动过程和资源管理。
Application 类
using System.Windows;
namespace MyWpfApp
{
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// 自定义启动逻辑
var mainWindow = new MainWindow();
mainWindow.Show();
}
protected override void OnExit(ExitEventArgs e)
{
// 清理资源
base.OnExit(e);
}
private void Application_DispatcherUnhandledException(object sender,
DispatcherUnhandledExceptionEventArgs e)
{
// 全局异常处理
MessageBox.Show($"发生错误: {e.Exception.Message}");
e.Handled = true;
}
}
}
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"
DispatcherUnhandledException="Application_DispatcherUnhandledException">
<Application.Resources>
<!-- 全局资源 -->
<Style TargetType="Button">
<Setter Property="Padding" Value="10,5" />
</Style>
</Application.Resources>
</Application>
窗口生命周期
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// 窗口事件
this.Loaded += MainWindow_Loaded;
this.Closing += MainWindow_Closing;
this.Closed += MainWindow_Closed;
this.Activated += MainWindow_Activated;
this.Deactivated += MainWindow_Deactivated;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// 窗口加载完成
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// 窗口即将关闭,可以取消关闭
var result = MessageBox.Show("确定要关闭吗?", "确认",
MessageBoxButton.YesNo);
if (result == MessageBoxResult.No)
{
e.Cancel = true;
}
}
private void MainWindow_Closed(object sender, EventArgs e)
{
// 窗口已关闭
}
private void MainWindow_Activated(object sender, EventArgs e)
{
// 窗口获得焦点
}
private void MainWindow_Deactivated(object sender, EventArgs e)
{
// 窗口失去焦点
}
}
控件系统
WPF 提供了丰富的内置控件,涵盖了常见的 UI 元素。
常用控件分类
按钮类
Button- 标准按钮RepeatButton- 重复触发按钮ToggleButton- 切换按钮CheckBox- 复选框RadioButton- 单选按钮
文本类
TextBox- 文本输入框RichTextBox- 富文本框TextBlock- 文本显示Label- 标签PasswordBox- 密码框
选择类
ComboBox- 下拉列表ListBox- 列表框ListView- 列表视图TreeView- 树形视图DataGrid- 数据网格
容器类
GroupBox- 分组框Expander- 可展开面板TabControl- 标签页Menu- 菜单ToolBar- 工具栏
控件示例
<StackPanel Margin="20">
<!-- 按钮 -->
<Button Content="点击我" Width="100" Margin="5" />
<!-- 文本框 -->
<TextBox Width="200" Margin="5"
Text="请输入文本" />
<!-- 复选框 -->
<CheckBox Content="记住我" Margin="5" />
<!-- 单选按钮 -->
<StackPanel Orientation="Horizontal" Margin="5">
<RadioButton Content="选项1" GroupName="Options" />
<RadioButton Content="选项2" GroupName="Options" />
</StackPanel>
<!-- 下拉列表 -->
<ComboBox Width="200" Margin="5">
<ComboBoxItem Content="选项1" />
<ComboBoxItem Content="选项2" />
<ComboBoxItem Content="选项3" />
</ComboBox>
<!-- 滑块 -->
<Slider Width="200" Minimum="0" Maximum="100"
Value="50" Margin="5" />
<!-- 进度条 -->
<ProgressBar Width="200" Height="20"
Value="70" Margin="5" />
</StackPanel>
自定义控件
// 自定义控件类
public class CustomButton : Button
{
static CustomButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomButton),
new FrameworkPropertyMetadata(typeof(CustomButton)));
}
// 依赖属性
public string CustomText
{
get { return (string)GetValue(CustomTextProperty); }
set { SetValue(CustomTextProperty, value); }
}
public static readonly DependencyProperty CustomTextProperty =
DependencyProperty.Register(
"CustomText",
typeof(string),
typeof(CustomButton),
new PropertyMetadata(string.Empty));
}
布局系统
WPF 提供了灵活的布局系统,支持响应式设计和自适应布局。
布局面板
StackPanel
按顺序排列子元素,支持水平和垂直方向
<StackPanel Orientation="Vertical">
<Button Content="按钮1" />
<Button Content="按钮2" />
<Button Content="按钮3" />
</StackPanel>
Grid
基于行和列的网格布局,最常用的布局面板
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="标题" />
<ContentControl Grid.Row="1" Grid.Column="1" />
</Grid>
WrapPanel
自动换行布局,子元素按顺序排列
<WrapPanel Orientation="Horizontal">
<Button Content="按钮1" Width="100" />
<Button Content="按钮2" Width="100" />
<Button Content="按钮3" Width="100" />
</WrapPanel>
DockPanel
停靠布局,子元素可以停靠在边缘
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Top"
Text="顶部" />
<TextBlock DockPanel.Dock="Left"
Text="左侧" />
<ContentControl />
</DockPanel>
Canvas
绝对定位布局,使用坐标定位子元素
<Canvas Width="300" Height="200">
<Button Canvas.Left="50" Canvas.Top="50"
Content="按钮1" />
<Button Canvas.Left="150" Canvas.Top="100"
Content="按钮2" />
</Canvas>
UniformGrid
均匀网格,所有单元格大小相同
<UniformGrid Rows="2" Columns="2">
<Button Content="1" />
<Button Content="2" />
<Button Content="3" />
<Button Content="4" />
</UniformGrid>
布局属性
<!-- 对齐属性 -->
<Button HorizontalAlignment="Left"
VerticalAlignment="Center" />
<!-- 边距和内边距 -->
<Button Margin="10,5,10,5"
Padding="15,8" />
<!-- 尺寸属性 -->
<Button Width="100" Height="30"
MinWidth="80" MinHeight="25"
MaxWidth="150" MaxHeight="40" />
<!-- 可见性 -->
<Button Visibility="Visible" />
<Button Visibility="Collapsed" />
<Button Visibility="Hidden" />
<!-- 透明度 -->
<Button Opacity="0.8" />