WPF 是 .NET 平台上的一个现代化 UI 框架,采用基于矢量的呈现引擎,旨在利用现代图形硬件,提供与分辨率无关的高质量用户界面。本文档基于官方概述,提炼 WPF 的核心功能,并通过图示和代码示例帮助读者快速上手。
一、WPF 是什么?
- 定义:WPF 是一个用于构建 Windows 桌面应用程序的 UI 框架,它集成了 XAML、控件、数据绑定、布局、2D/3D 图形、动画、样式、模板、文档、媒体和文本排版等功能。
- 两种实现 :
- .NET 版本:开源,运行在 .NET 上(仅 Windows)。
- .NET Framework 版本:作为 Windows 组件随 .NET Framework 分发。
- 为何升级到 .NET:更好的性能、新的 API、语言改进、辅助功能增强、工具更新等。
二、WPF 编程模型
WPF 应用程序的编程体验类似于其他 .NET 框架(如 ASP.NET、Windows Forms):
- 实例化类
- 设置属性
- 调用方法
- 处理事件
此外,WPF 引入了两个增强特性:
- 依赖属性:支持值继承、更改通知、节省内存。
- 路由事件:支持隧道(预览)和冒泡两种传播方式。
标记与代码隐藏
WPF 将外观 (XAML 标记)与行为(代码隐藏)分离,类似于 ASP.NET 的 Web Forms。
xml
<!-- MainWindow.xaml -->
<Window x:Class="WpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Hello WPF" Height="200" Width="300">
<StackPanel>
<Button Name="btnClick" Click="BtnClick_Click">Click Me</Button>
<TextBlock Name="txtMessage" Margin="5"/>
</StackPanel>
</Window>
csharp
// MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent(); // 合并标记与代码
}
private void BtnClick_Click(object sender, RoutedEventArgs e)
{
txtMessage.Text = $"Button clicked at {DateTime.Now}";
}
}
关键点 :
x:Class指定代码隐藏类,InitializeComponent()在构造函数中调用以加载 XAML 定义的 UI。
三、核心功能速览
1. 布局系统
WPF 布局基于相对定位 和两阶段协商(Measure 和 Arrange),提供灵活的布局控件:
| 布局控件 | 作用 |
|---|---|
Canvas |
绝对定位,子控件指定坐标 |
DockPanel |
子控件停靠到边缘 |
Grid |
按行/列排列,类似表格 |
StackPanel |
垂直或水平堆叠 |
WrapPanel |
自动换行 |
VirtualizingStackPanel |
支持虚拟化的堆叠 |
示例:DockPanel 布局
xml
<DockPanel>
<Button DockPanel.Dock="Top" Background="LightBlue">Top</Button>
<Button DockPanel.Dock="Bottom" Background="LightGreen">Bottom</Button>
<Button DockPanel.Dock="Left" Background="LightCoral">Left</Button>
<Button Background="LightGray">Fill</Button>
</DockPanel>
附加属性 :
DockPanel.Dock是父控件提供给子控件的属性,用于指定停靠位置。
2. 数据绑定
数据绑定引擎自动在 UI 控件和数据源之间同步数据。绑定声明在 XAML 中完成:
xml
<Window DataContext="{Binding MyPerson}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
<TextBox Text="{Binding Age, Mode=TwoWay}" />
</StackPanel>
</Window>
- 绑定源 :可以是任何 .NET 对象(需实现
INotifyPropertyChanged)。 - 绑定目标:依赖属性。
- 模式 :
OneWay、TwoWay、OneTime、OneWayToSource。
图示:
数据源 (Person) ←→ 绑定引擎 ←→ UI 控件
Name = "张三" TextBox.Text = "张三"
3. 控件
WPF 提供了丰富的内置控件,按功能分类:
- 按钮 :
Button、RepeatButton - 数据显示 :
DataGrid、ListView、TreeView - 日期选择 :
Calendar、DatePicker - 对话框 :
OpenFileDialog、SaveFileDialog - 数字墨迹 :
InkCanvas、InkPresenter - 文档 :
DocumentViewer、FlowDocumentReader - 输入 :
TextBox、RichTextBox、PasswordBox - 布局 :
Grid、StackPanel、DockPanel等 - 媒体 :
Image、MediaElement - 菜单 :
Menu、ContextMenu、ToolBar - 选择 :
CheckBox、ComboBox、ListBox、RadioButton、Slider - 用户信息 :
Label、ProgressBar、ToolTip
4. 图形与动画
WPF 图形系统具有以下特点:
- 与分辨率无关:基本单位是 1/96 英寸的"设备无关像素"。
- 高精度:使用双精度浮点数。
- 硬件加速:利用 GPU 减少 CPU 负载。
2D 图形:提供形状(Rectangle、Ellipse)、几何图形(Path)、画笔(SolidColorBrush、LinearGradientBrush)等。
xml
<Rectangle Width="100" Height="50" Fill="Blue" RadiusX="10" RadiusY="10"/>
<Path Data="M 10,10 L 50,10 L 30,50 Z" Fill="Red" Stroke="Black"/>
3D 图形:可嵌入 3D 模型并与 2D 元素交互。
动画 :通过 Storyboard 和 Timeline 实现属性动画。
xml
<Button Content="Animate">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width"
From="100" To="200" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
5. 文本与排版
WPF 提供高质量的文本呈现:
- 支持 OpenType 字体
- ClearType 增强
- 硬件加速文本渲染
- 文本与图形、动画集成
xml
<TextBlock FontFamily="Segoe UI" FontSize="24" FontWeight="Bold">
Hello <Run Foreground="Red">WPF</Run>
</TextBlock>
四、自定义应用外观
1. 内容模型
不同控件支持不同的内容类型:
- ContentControl :可包含单个任意对象(如
Button)。 - HeaderedContentControl :包含内容和标题(如
GroupBox)。 - ItemsControl :包含集合(如
ListBox)。 - HeaderedItemsControl :包含标题和集合(如
TreeViewItem)。
xml
<Button>
<StackPanel Orientation="Horizontal">
<Image Source="icon.png" Width="16" Height="16"/>
<TextBlock Text="Click Me"/>
</StackPanel>
</Button>
2. 样式
样式用于集中定义一组属性值,可应用于多个元素。
xml
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="Orange"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Margin" Value="5"/>
</Style>
</Window.Resources>
<Button>Styled Button</Button>
3. 模板
- 控件模板:彻底改变控件外观,但保留行为。
- 数据模板:定义数据对象的可视化方式。
xml
<!-- 控件模板:圆形按钮 -->
<Button>
<Button.Template>
<ControlTemplate TargetType="Button">
<Ellipse Fill="Green" Width="80" Height="80">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Ellipse>
</ControlTemplate>
</Button.Template>
Click
</Button>
xml
<!-- 数据模板:自定义列表项外观 -->
<ListBox ItemsSource="{Binding Tasks}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsCompleted}"/>
<TextBlock Text="{Binding Name}" Margin="5,0"/>
<TextBlock Text="{Binding Priority}" Foreground="Gray"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
4. 资源
资源允许在应用程序范围内共享对象(画刷、样式、模板等),提高重用性和维护性。
xml
<Window.Resources>
<SolidColorBrush x:Key="GlobalBrush" Color="LightBlue"/>
<Style TargetType="Button" x:Key="BtnStyle">
<Setter Property="Background" Value="{StaticResource GlobalBrush}"/>
</Style>
</Window.Resources>
<Button Style="{StaticResource BtnStyle}">Shared Style</Button>
5. 自定义控件
当现有控件无法满足需求时,可通过以下方式创建自定义控件:
| 基类 | 适用场景 |
|---|---|
UserControl |
组合多个现有控件,快速创建可复用组件 |
Control |
需要模板化外观和自定义行为,类似内置控件 |
FrameworkElement |
需要自定义渲染逻辑(如绘图) |
五、总结
WPF 通过声明式标记 (XAML)和代码隐藏 的分离,结合强大的依赖属性 、路由事件 、数据绑定 、样式与模板 ,为构建现代桌面应用提供了完整而灵活的解决方案。其硬件加速的图形系统 和与分辨率无关的布局,确保了应用在不同显示设备上的高质量呈现。无论是简单的业务系统,还是复杂的交互式设计工具,WPF 都能提供坚实的基础。