WPF 开发指南

构建现代桌面应用程序的完整指南

什么是 WPF?

WPF (Windows Presentation Foundation) 是微软推出的用于构建 Windows 桌面应用程序的 UI 框架。它提供了强大的图形渲染能力、丰富的控件库、灵活的布局系统和数据绑定机制,使开发者能够创建美观、高性能的桌面应用。

🎨

声明式 UI

使用 XAML 声明式语言构建用户界面,实现设计与逻辑的分离

🔗

数据绑定

强大的数据绑定系统,实现 UI 与数据的自动同步

🎭

样式与模板

灵活的样式和模板系统,完全自定义控件外观

高性能

基于 DirectX 的渲染引擎,提供流畅的图形体验

🎬

动画与媒体

内置动画系统和媒体支持,创建丰富的交互体验

🔧

可扩展性

支持自定义控件和行为,满足各种业务需求

💡 为什么选择 WPF?

WPF 是构建企业级桌面应用的理想选择。它提供了完整的开发框架,从基础的 UI 控件到高级的图形渲染,从数据绑定到 MVVM 架构,应有尽有。无论是简单的工具应用还是复杂的业务系统,WPF 都能胜任。

安装环境

开始 WPF 开发之前,需要准备以下开发环境:

1

安装 Visual Studio

下载并安装 Visual Studio 2022,选择 ".NET 桌面开发" 工作负载。

# 通过命令行安装 Visual Studio Build Tools
winget install Microsoft.VisualStudio.2022.BuildTools --override "--wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktopBuildTools"
2

安装 .NET SDK

安装最新的 .NET SDK(推荐 .NET 8 或更高版本)。

# 检查已安装的 .NET 版本
dotnet --version

# 安装 .NET 8 SDK
winget install Microsoft.DotNet.SDK.8
3

安装 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" />

官方文档

Microsoft Learn

WPF 官方文档和学习资源

访问文档 →

.NET API 参考

完整的 WPF API 文档

查看 API →

GitHub 仓库

WPF 源代码和问题跟踪

查看源码 →

社区资源

Stack Overflow

WPF 相关问题和解答

浏览问题 →

GitHub

开源 WPF 项目和库

探索项目 →

NuGet

WPF 相关 NuGet 包

搜索包 →