WPF 入门教程(二)
四.内容控件
1.Control基类
WPF中的Control类是构建交互式控件(如Button、TextBox等)的核心基类,支持模板化和样式主题。
1.1 Control类的核心特性
1.1.1 模板化
通过ControlTemplate自定义控件外观(如圆角按钮)
1.1.2 内容模型
Content属性支持任意对象(如Button可包含图像或文本)
1.1.3 样式与主题
集成系统主题,支持Style和Trigger实现动态样式
1.1.4 基础属性
Background/Foreground(画刷)、FontFamily/FontSize(文本格式)、BorderThickness(边框)
1.2 简单使用
<Window x:Class="TestWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Control>
<Control.Template>
<ControlTemplate>
<Border Width="200" Height="42" CornerRadius="5" BorderThickness="1" BorderBrush="Gray" Padding="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox BorderThickness="0" VerticalContentAlignment="Center"/>
<TextBlock Text="🔍" Grid.Column="1" VerticalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</Grid>
</Window>

2.ContentControl基类
用于承载和显示单一内容对象,作为Control的直接子类,它扩展了内容模型能力,是按钮(Button)、标签(Label)等交互控件的基类。
3.Button按钮
3.1 基础概念
用于点击的用户交互控件
继承关系:DispatcherObject → DependencyObject → Visual → UIElement → FrameworkElement → Control → ButtonBase → Button
核心功能:
- 用户交互触发操作
- 支持内容自定义
- 支持命令绑定(MVVM模式) *
3.2 基本用法
<Button Content="按钮一" Width="80" Height="36" Click="Button_Click"/>
<Button Width="80" Height="36">
<StackPanel Orientation="Horizontal">
<TextBlock Text="📂"/>
<Separator Width="1" Margin="5,0"/>
<TextBlock Text="打开"/>
</StackPanel>
</Button>
using System.Windows;
namespace TestWpfApp
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Hello, World!");
}
}
}
3.3 核心属性
3.3.1 内容属性
| 属性 | 说明 | 示例 |
|---|---|---|
| Content | 按钮显示内容 | <Button Content="提交"/> |
| ContentTemplate | 内容显示模板 | <Button.ContentTemplate><DataTemplate>...</DataTemplate></Button.ContentTemplate> |
3.3.2 外观属性
| 属性 | 说明 | 常用值 |
|---|---|---|
| Background | 背景色 | "Red", "#FFFF0000" |
| Foreground | 前景色 | "White", "#FFFFFFFF" |
| BorderBrush | 边框颜色 | "Black" |
| BorderThickness | 边框粗细 | "1", "2,2,2,2" |
| Padding | 内边距 | "5", "10,5,10,5" |
| Font系列 | 字体设置 | FontSize="14", FontWeight="Bold" |
3.3.3 交互属性
| 属性 | 说明 | 示例 |
|---|---|---|
| IsEnabled | 是否可用 | IsEnabled="False" |
| IsDefault | 默认按钮(响应Enter) | IsDefault="True" |
| IsCancel | 取消按钮(响应Esc) | IsCancel="True" |
| ClickMode | 点击触发方式 | Press/Release/Hover |
3.4 事件处理
| 事件 | 类型 | 说明 |
|---|---|---|
| Click | 路由事件 | 按钮点击事件 |
| PreviewMouseDown | 隧道事件 | 鼠标按下前触发 |
| MouseDown | 冒泡事件 | 鼠标按下时触发 |
| PreviewMouseUp | 隧道事件 | 鼠标释放前触发 |
| MouseUp | 冒泡事件 | 鼠标释放时触发 |
3.5 高级用法 *
带有圆角、状态改变、图标的按钮
<Button Width="120" Height="36" Padding="5" Click="OpenFolder_Click">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Cursor="Hand" Padding="{TemplateBinding Padding}" CornerRadius="5" BorderThickness="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontSize" Value="16"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="/Resources/Images/icon_folder.png"/>
<TextBlock Text="打开目录" Grid.Column="1" VerticalAlignment="Center" Margin="5,0,0,0"/>
</Grid>
</Button.Content>
</Button>

3.6 MessageBox 使用
MessageBox 是 WPF 中用于显示简单对话框的系统组件,常用于提示、确认和获取用户简单反馈。
3.6.1 基础用法
简单消息提示
MessageBox.Show("操作已完成!");
带标题的消息框
MessageBox.Show("文件保存成功", "系统提示");
带按钮的消息框
MessageBox.Show("确定要删除吗?", "确认删除", MessageBoxButton.YesNo);
3.6.2 MessageBoxButton 枚举
| 值 | 显示的按钮 |
|---|---|
| OK | 确定 |
| OKCancel | 确定/取消 |
| YesNo | 是/否 |
| YesNoCancel | 是/否/取消 |
3.6.3 MessageBoxImage 枚举
MessageBox.Show("磁盘空间不足", "警告",
MessageBoxButton.OK,
MessageBoxImage.Warning);
常用图标类型:
- None - 无图标
- Error - 错误(红色X)
- Question - 问号
- Warning - 感叹号
- Information - 信息(i图标)
3.6.4 MessageBoxResult 返回值
MessageBoxResult result = MessageBox.Show("继续操作吗?",
"确认",
MessageBoxButton.YesNoCancel);
switch(result)
{
case MessageBoxResult.Yes:
// 用户点击"是"
break;
case MessageBoxResult.No:
// 用户点击"否"
break;
case MessageBoxResult.Cancel:
// 用户点击"取消"
break;
}
3.6.5 设置默认按钮
MessageBox.Show("确认提交吗?",
"请确认",
MessageBoxButton.YesNo,
MessageBoxImage.Question,
MessageBoxResult.No); // 默认选中"否"
3.6.6 自定义窗口所有者
// 确保消息框显示在主窗口上方
MessageBox.Show(Application.Current.MainWindow,
"这是一个重要提示",
"系统消息");
4.CheckBox 复选框
CheckBox 是 WPF 中常用的选择控件,允许用户在两种或三种状态间切换。
4.1 核心属性
| 属性 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| IsChecked | bool? | 选中状态(true/false/null) | True, False, Null |
| IsThreeState | bool | 是否允许第三种状态 | True, False |
| Content | object | 显示内容 | "选项1", |
| ContentTemplate | DataTemplate | 内容模板 | 自定义数据模板 |
4.2 状态类型
- 选中(true)
- 未选中(false)
- 不确定(null)
4.3 简单使用
<Window x:Class="TestWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="请选择爱好:"/>
<StackPanel Orientation="Horizontal" x:Name="hobbyStackPanel">
<CheckBox Content="唱歌" IsChecked="True" Checked="CheckBox_Checked"/>
<CheckBox Content="跳舞" Checked="CheckBox_Checked"/>
<CheckBox Content="打篮球" IsChecked="{x:Null}" Checked="CheckBox_Checked"/>
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="确定" Click="Confirm_Click"/>
<Button Content="清空" Click="Clear_Click"/>
</StackPanel>
</StackPanel>
</Grid>
</Window>
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace TestWpfApp
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
if(sender is CheckBox checkBox)
{
if (checkBox.IsChecked==true && checkBox.Content.Equals("打篮球"))
{
MessageBox.Show("这个不让选。");
checkBox.IsChecked = false;
}
}
}
private void Confirm_Click(object sender, RoutedEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (var item in hobbyStackPanel.Children)
{
if (item is CheckBox checkBox && checkBox.IsChecked == true)
{
sb.AppendLine(checkBox.Content.ToString());
}
}
MessageBox.Show("你选择的爱好是:"+sb.ToString());
}
private void Clear_Click(object sender, RoutedEventArgs e)
{
foreach (var item in hobbyStackPanel.Children)
{
if (item is CheckBox checkBox && checkBox.IsChecked == true)
{
checkBox.IsChecked = false;
}
}
}
}
}

5.RadioButton 单选框
WPF中用于实现单选功能的控件,通常用于一组互斥的选项选择。
5.1 基础特性与用法
基本结构
<RadioButton Content="选项1" IsChecked="True"/>
<RadioButton Content="选项2"/>
<RadioButton Content="选项3"/>
核心属性
| 属性 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| IsChecked | bool | 是否选中 | True, False |
| GroupName | string | 分组名称 | "Group1", "Group2" |
| Content | object | 显示内容 | "男", <Image>等 |
| ContentTemplate | DataTemplate | 内容模板 | 自定义数据模板 |
5.2 分组机制
1). 隐式分组(同父容器)
<StackPanel>
<RadioButton Content="选项A"/>
<RadioButton Content="选项B"/> <!-- 与选项A互斥 -->
</StackPanel>
2). 显式分组(GroupName)
<RadioButton Content="红色" GroupName="Color"/>
<RadioButton Content="绿色" GroupName="Color"/> <!-- 颜色组 -->
<RadioButton Content="大号" GroupName="Size"/>
<RadioButton Content="小号" GroupName="Size"/> <!-- 尺寸组 -->
3).复杂分组示例
<StackPanel>
<GroupBox Header="颜色选择">
<RadioButton Content="红色" GroupName="Color"/>
<RadioButton Content="蓝色" GroupName="Color"/>
</GroupBox>
<GroupBox Header="尺寸选择">
<RadioButton Content="大号" GroupName="Size"/>
<RadioButton Content="小号" GroupName="Size"/>
</GroupBox>
</StackPanel>
5.3 事件处理
| 事件 | 触发时机 |
|---|---|
| Checked | 被选中时触发 |
| Unchecked | 取消选中时触发 |
| Click | 点击时触发 |
6.RepeatButton 重复按钮
RepeatButton 是 WPF 中的一个特殊按钮控件,它在用户按住按钮时会重复触发点击事件,适合实现增减按钮、滚动控制等需要连续操作的功能。
6.1 与普通 Button 的区别
| 特性 | Button | RepeatButton |
|---|---|---|
| 触发方式 | 点击一次触发一次 | 按住时重复触发 |
| 首次触发延迟 | 无 | 有初始延迟 |
| 重复间隔 | 无 | 可配置间隔 |
继承关系:DispatcherObject → DependencyObject → Visual → UIElement → FrameworkElement → Control → ButtonBase → RepeatButton
6.2 基础用法
<RepeatButton Content="+" Width="30" Height="30" Click="Increase_Click"/>
private int _value = 0;
private void Increase_Click(object sender, RoutedEventArgs e)
{
_value++;
txtValue.Text = _value.ToString();
}
6.3 关键属性
|属性 |类型 |默认值| 说明| |-|-|-|-| |Delay |int |300(ms) |首次触发前的延迟时间| |Interval |int| 100(ms) |重复触发的时间间隔|
6.4 事件处理
| 事件 | 描述 |
|---|---|
| Click | 每次触发时发生 |
| PreviewMouseDown | 鼠标按下时(首次触发前) |
| PreviewMouseUp | 鼠标释放时 |
7.Label标签
Label 是 WPF 中用于显示文本内容的轻量级控件,相比 TextBlock 提供了更多与表单输入控件协作的功能。。
7.1 基础特性与用法
基本结构
<Label Content="用户名:" Target="{Binding ElementName=txtUserName}"/>
<TextBox x:Name="txtUserName"/>
核心属性
| 属性 | 类型 | 说明 | 示例值 |
|---|---|---|---|
| Content | object | 显示内容 | "密码:", <Image>等 |
| Target | UIElement | 关联的焦点目标控件 | {Binding ElementName=txtBox} |
| ContentTemplate | DataTemplate | 内容显示模板 | 自定义数据模板 |
7.2 与输入控件协作
7.2.1 快捷键支持(AccessText)
<Label Content="_Username:" Target="{Binding ElementName=txtUser}"/>
<TextBox x:Name="txtUser"/>
<!-- 按Alt+U将聚焦到文本框 -->
7.2.2 多目标关联
<StackPanel>
<Label x:Name="lblGroup" Content="个人资料"/>
<CheckBox Content="姓名" Target="{Binding ElementName=lblGroup}"/>
<CheckBox Content="年龄" Target="{Binding ElementName=lblGroup}"/>
</StackPanel>
7.3 内容呈现
<Label Content="静态文本标签"/>
<Label>
<StackPanel Orientation="Horizontal">
<Image Source="warning.png" Width="16"/>
<TextBlock Text="重要提示" FontWeight="Bold"/>
</StackPanel>
</Label>
8.TextBlock文字块
TextBlock 是 WPF 中最基础且功能强大的文本显示控件,相比 Label 控件更轻量且专注于文本呈现。
8.1 基础文本显示
文本设置方式
<!-- 直接文本 -->
<TextBlock Text="Hello World"/>
<!-- 内容属性语法 -->
<TextBlock>直接内容</TextBlock>
<!-- 多行文本 -->
<TextBlock>
<Run Text="123"/>
<LineBreak/>
<Run Text="456"/>
</TextBlock>
基础属性配置
| 属性 | 类型 | 说明 | 示例 |
|---|---|---|---|
| TextWrapping | TextWrapping | 换行控制 | Wrap, NoWrap |
| TextTrimming | TextTrimming | 溢出处理 | CharacterEllipsis, WordEllipsis |
| TextAlignment | TextAlignment | 对齐方式 | Left, Center, Right |
| LineHeight | double | 行间距 | 20 |
| LineStackingStrategy | enum | 行高计算 | BlockLineHeight, MaxHeight |
8.2 高级文本格式化
内联元素类型
<TextBlock>
<Run Text="普通文本 "/>
<LineBreak/>
<Bold>加粗文本</Bold>
<Italic>斜体文本</Italic>
<Underline>
<Span>组合</Span>
</Underline>
<Hyperlink NavigateUri="https://example.com">超链接</Hyperlink>
</TextBlock>
8.3 视觉样式控制
字体控制属性
| 属性 | 说明 | 示例值 |
|---|---|---|
| FontFamily | 字体 | "Arial", "微软雅黑" |
| FontSize | 字号 | 14, 18 |
| FontWeight | 字重 | Normal, Bold |
| FontStyle | 样式 | Normal, Italic |
| TextDecorations | 装饰线 | Underline, Strikethrough |
高级渲染控制
<!-- 抗锯齿优化 -->
<TextBlock TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"/>
<!-- 文本阴影 -->
<TextBlock Text="特效文本">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="4" ShadowDepth="3" Color="#88000000"/>
</TextBlock.Effect>
</TextBlock>
8.4 渲染性能优化
<!-- 启用硬件渲染 -->
<TextBlock CacheMode="BitmapCache"/>
<!-- 大量文本优化 -->
<TextBlock Text="{Binding LogContent}"
TextOptions.TextFormattingMode="Display"
IsTextSelectionEnabled="False"/>
8.5 超链接
<TextBlock>
<Hyperlink NavigateUri="https://www.baidu.com" RequestNavigate="Hyperlink_RequestNavigate">
点击访问
</Hyperlink>
</TextBlock>
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true });
}
9.TextBox输入框
TextBox 是 WPF 中用于文本输入的基本控件
9.1 主要特点
- 支持单行和多行文本输入
- 提供文本选择、复制、粘贴等基本编辑功能
- 支持数据绑定和格式化
- 可自定义外观和行为
9.2 基本用法
<Window x:Class="TestWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWpfApp"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="350">
<Grid>
<GroupBox Header="笔记编辑" Margin="10" Padding="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="标题:" VerticalAlignment="Center"/>
<!--单行文本框-->
<TextBox Grid.Column="1" FontSize="16" FontWeight="Bold"/>
</Grid>
<Grid Grid.Row="1" Margin="0,5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="笔记描述:"/>
<!--多行文本框-->
<TextBox Grid.Row="1" FontSize="16" TextWrapping="Wrap" AcceptsReturn="True" VerticalScrollBarVisibility="Auto"/>
</Grid>
<Grid Grid.Row="2" Margin="0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="链接:" VerticalAlignment="Center"/>
<!--只读可复制文本框-->
<TextBox Text="www.diandiandidi.club" IsReadOnly="True" BorderThickness="0" Grid.Column="1" />
</Grid>
</Grid>
</GroupBox>
</Grid>
</Window>

9.3 常用属性
文本相关
- Text: 获取或设置文本框中的文本内容
- TextAlignment: 文本对齐方式 (Left, Right, Center, Justify)
- TextWrapping: 文本换行方式 (NoWrap, Wrap, WrapWithOverflow)
- LineHeight: 行高
- MaxLength: 最大输入字符数
外观相关
- Background: 背景色
- oreground: 前景色(文本颜色)
- BorderBrush: 边框颜色
- BorderThickness: 边框粗细
- FontFamily: 字体
- FontSize: 字体大小
- FontWeight: 字体粗细
- FontStyle: 字体样式 (Normal, Italic, Oblique)
行为相关
- IsReadOnly: 是否只读
- IsEnabled: 是否启用
- AcceptsReturn: 是否接受回车键(用于多行输入)
- AcceptsTab: 是否接受 Tab 键
- SpellCheck.IsEnabled: 是否启用拼写检查
- HorizontalScrollBarVisibility: 水平滚动条可见性
- VerticalScrollBarVisibility: 垂直滚动条可见性
- SelectionBrush: 文本选中时的背景色
- SelectionOpacity: 文本选中时背景色的透明度
- CaretBrush: 光标颜色
9.4 水印
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Text" Value="请输入内容..."/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Text" Value=""/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
9.5 事件处理
- TextChanged: 文本内容改变时触发
- GotFocus: 获得焦点时触发
- LostFocus: 失去焦点时触发
- PreviewTextInput: 文本输入前触发
- KeyDown: 按键按下时触发
- KeyUp: 按键释放时触发
10.PasswordBox密码输入框
PasswordBox 是 WPF 中专门用于密码输入的控件,不支持密码属性绑定。
主要特点:
- 专为密码输入设计,输入字符默认显示为掩码(圆点或星号)
- 不直接暴露密码文本,提供安全属性访问密码
- 不支持数据绑定 Password 属性(出于安全考虑)
- 提供密码强度控制功能
- 可自定义密码显示字符和外观
10.1 简单用法
<PasswordBox Password="123456" PasswordChar="*"/>

10.2 常用属性
密码相关
•Password: 获取或设置密码框中包含的密码(不直接绑定) •PasswordChar: 获取或设置用于屏蔽密码的字符(默认是圆点●) 外观相关
Background: 背景色
Foreground: 前景色(文本颜色)
BorderBrush: 边框颜色
BorderThickness: 边框粗细
FontFamily: 字体
FontSize: 字体大小
FontWeight: 字体粗细
SelectionBrush: 文本选中时的背景色
SelectionOpacity: 文本选中时背景色的透明度
CaretBrush: 光标颜色 行为相关
MaxLength: 最大输入字符数
IsEnabled: 是否启用
PasswordChanged: 密码更改时触发的事件
10.3 密码安全处理
安全获取密码
// 不安全方式(字符串会留在内存中)
string password = pwdBox.Password;
// 安全方式(推荐)
System.Security.SecureString securePwd = pwdBox.SecurePassword;
// 将 SecureString 转换为字符串
string ConvertToUnsecureString(SecureString securePassword)
{
if (securePassword == null)
return string.Empty;
IntPtr unmanagedString = IntPtr.Zero;
try
{
unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}
}
11.RichTextBox富文本框
RichTextBox 是 WPF 中用于显示和编辑富文本内容的控件,支持多种文本格式、段落样式、嵌入对象等高级功能。
11.1 核心特点
- 支持富文本格式(RTF)
- 可包含多种字体、颜色、样式混合的文本
- 支持段落、列表、表格等复杂排版
- 允许嵌入图像、超链接等非文本元素
- 提供文本选择、格式查询等高级功能
- 基于 FlowDocument 文档模型
11.2 与TextBox对比
| 特性 | TextBox | RichTextBox |
|---|---|---|
| 文本格式 | 纯文本 | 富文本 |
| 性能 | 高 | 较低 |
| 内存占用 | 少 | 较多 |
| 功能 | 基础编辑 | 高级排版 |
| 使用场景 | 简单输入 | 复杂文档 |
12.Tooltip 提示
ToolTip 是 WPF 中用于显示额外信息的弹出式控件,当用户将鼠标悬停在元素上时显示提示内容。
12.1 核心特点
- 轻量级信息展示:不干扰主界面布局
- 悬停触发:默认鼠标悬停时显示
- 富内容支持:可包含任意可视化元素
- 高度可定制:完全控制外观和行为
- 自动定位:智能避开屏幕边缘
12.2 基本使用
简单文本提示
<Button Content="提交" ToolTip="点击提交表单数据"/>
通过属性设置
<Button Content="保存">
<Button.ToolTip>
<ToolTip Content="保存当前文档"/>
</Button.ToolTip>
</Button>
多行文本提示
<TextBox>
<TextBox.ToolTip>
<ToolTip>
<StackPanel>
<TextBlock Text="用户名输入要求:" FontWeight="Bold"/>
<TextBlock Text="1. 长度6-20个字符"/>
<TextBlock Text="2. 只能包含字母和数字"/>
</StackPanel>
</ToolTip>
</TextBox.ToolTip>
</TextBox>
12.3 核心属性
内容属性
- Content:基础内容属性
- ContentTemplate:定义内容模板
- ContentStringFormat:内容字符串格式化
显示行为
- Placement:定位方式 (Bottom, Top, Left, Right, Mouse等)
- HorizontalOffset/VerticalOffset:显示偏移量
- PlacementRectangle:相对定位矩形区域
- PlacementTarget:指定相对定位的元素
- StaysOpen:是否保持打开状态
- IsOpen:控制打开/关闭状态
- InitialShowDelay:初始显示延迟(ms)
- ShowDuration:显示持续时间(ms)
- BetweenShowDelay:两次显示间隔(ms)
视觉样式
- Background:背景色
- Foreground:前景色
- BorderBrush:边框颜色
- BorderThickness:边框粗细
- FontFamily/FontSize:字体设置
- Padding:内边距
- HasDropShadow:是否显示阴影
12.5 交互控制
编程控制显示
// 创建ToolTip实例
ToolTip customTip = new ToolTip();
customTip.Content = "自定义提示";
customTip.Placement = PlacementMode.Right;
// 关联到元素
Button btn = new Button();
btn.Content = "测试按钮";
btn.ToolTip = customTip;
// 手动控制显示
customTip.IsOpen = true;
// 5秒后自动关闭
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(5);
timer.Tick += (s, e) => { customTip.IsOpen = false; timer.Stop(); };
timer.Start();
处理ToolTip事件
<Button Content="事件测试">
<Button.ToolTip>
<ToolTip x:Name="testToolTip"
Opened="ToolTip_Opened"
Closed="ToolTip_Closed"
Content="事件演示ToolTip"/>
</Button.ToolTip>
</Button>
private void ToolTip_Opened(object sender, RoutedEventArgs e)
{
Debug.WriteLine("ToolTip已显示");
}
private void ToolTip_Closed(object sender, RoutedEventArgs e)
{
Debug.WriteLine("ToolTip已关闭");
}
12.6 多元素共享ToolTip
<StackPanel>
<StackPanel.ToolTip>
<ToolTip x:Name="sharedToolTip" Content="共享提示信息"/>
</StackPanel.ToolTip>
<Button Content="按钮1" ToolTip="{Binding ElementName=sharedToolTip}"/>
<TextBox Text="文本框" ToolTip="{Binding ElementName=sharedToolTip}"/>
</StackPanel>
13.Popup浮窗
Popup 是 WPF 中用于创建浮动窗口的控件,它可以在主窗口上方显示内容,常用于下拉菜单、提示框、上下文菜单等场景。
13.1 基本概念与特性
核心特点
- 独立于主窗口的浮动层:显示在主窗口内容之上
- 灵活定位:可相对于任意元素或屏幕位置定位
- 非模态交互:不阻止与其他窗口元素的交互
- 自动隐藏:默认点击外部区域自动关闭
- 富内容支持:可包含任意可视化元素
- 动画支持:可添加显示/隐藏动画效果 与类似控件对比
| 特性 | Popup | ToolTip | ContextMenu |
|---|---|---|---|
| 触发方式 | 编程控制 | 悬停 | 右键点击 |
| 交互性 | 完全交互 | 只读 | 菜单交互 |
| 显示控制 | IsOpen属性 | 自动 | 自动 |
| 定位方式 | 灵活定位 | 跟随鼠标 | 跟随鼠标 |
13.2 基本使用
1.简单Popup声明
<Popup x:Name="simplePopup" Placement="Mouse">
<Border Background="White" BorderBrush="Gray" BorderThickness="1">
<TextBlock Margin="10" Text="这是一个简单的Popup"/>
</Border>
</Popup>
2.通过代码控制显示
// 显示Popup
simplePopup.IsOpen = true;
// 关闭Popup
simplePopup.IsOpen = false;
3.绑定触发按钮
<StackPanel>
<CheckBox x:Name="popupButton" Content="显示Popup"/>
<Popup IsOpen="{Binding IsChecked, ElementName=popupButton}"
PlacementTarget="{Binding ElementName=popupButton}">
<Border Background="LightYellow" Padding="10">
<TextBlock Text="绑定按钮状态的Popup"/>
</Border>
</Popup>
</StackPanel>
13.3 核心属性
定位属性
- Placement:定位方式 (Absolute, Relative, Mouse, Bottom, Top等12种)
- PlacementTarget:定位参考元素
- PlacementRectangle:相对定位的矩形区域
- HorizontalOffset/VerticalOffset:偏移量
显示行为
- IsOpen:控制显示/隐藏状态
- StaysOpen:是否在失去焦点时自动关闭
- AllowsTransparency:是否允许透明背景
- PopupAnimation:内置动画效果 (None, Fade, Scroll, Slide)
- IsHitTestVisible:是否响应鼠标事件
视觉样式
- Child:Popup内容
- Width/Height:尺寸设置
- MaxWidth/MaxHeight:最大尺寸
- Background:背景色
- Padding:内边距
13.4 交互控制
处理Popup事件
<Popup x:Name="eventPopup" Opened="Popup_Opened" Closed="Popup_Closed">
<!-- 内容 -->
</Popup>
保持焦点控制
<Popup x:Name="focusPopup" StaysOpen="True">
<StackPanel>
<TextBox x:Name="popupTextBox"/>
<Button Content="关闭" Click="ClosePopup_Click"/>
</StackPanel>
</Popup>
14.Image 图像
Image 是 WPF 中用于显示图像的控件,支持多种图像格式和高级图像处理功能。
14.1 基本概念与特性
核心特点
- 多格式支持:BMP、PNG、JPEG、GIF、TIFF等
- 多种加载方式:文件路径、URI、内存流、资源
- 显示控制:拉伸、裁剪、旋转、透明度
- 高性能渲染:硬件加速支持
- 动画支持:不支持GIF动画播放 支持的图像格式
| 格式 | 特性 | 适用场景 |
|---|---|---|
| PNG | 无损压缩、透明通道 | 高质量图像、透明背景 |
| JPEG | 有损压缩、小文件 | 照片、实景图像 |
| BMP | 无压缩、大文件 | 需要无损编辑的图像 |
| GIF | 256色、支持动画 | 简单动画、小图标 |
| TIFF | 高质量、多页 | 专业图像处理 |
14.2 基本使用方式 从文件加载
<Image Source="C:\Users\luyuanwen\Desktop\图片\111.gif"/>
从项目资源加载
<!-- 添加图像到项目Resources文件夹 -->
<Image Source="Resources/icon.png"/>
从URI加载
<Image Source="https://www.diandiandidi.club/favicon.ico"/>
代码加载
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri("pack://application:,,,/Resources/image.png");
bitmap.EndInit();
imageControl.Source = bitmap;
14.3 核心属性
图像源属性
- Source:图像源(BitmapImage、DrawingImage等)
- Stretch:拉伸方式(None、Fill、Uniform、UniformToFill)
- StretchDirection:拉伸方向(UpOnly、DownOnly、Both)
视觉属性
- Opacity:透明度(0.0-1.0)
- OpacityMask:不透明蒙版
- RenderTransform:渲染变换(旋转、缩放等)
- Clip:裁剪区域
布局属性
- Width/Height:显式尺寸
- MaxWidth/MaxHeight:最大尺寸
- MinWidth/MinHeight:最小尺寸
14.4 高级用法
图像裁剪
<Image Source="photo.jpg">
<Image.Clip>
<EllipseGeometry Center="100,100" RadiusX="80" RadiusY="80"/>
</Image.Clip>
</Image>
图像变换
<Image Source="photo.jpg">
<Image.RenderTransform>
<TransformGroup>
<RotateTransform Angle="15"/>
<ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
图像蒙版
<Image Source="https://www.diandiandidi.club/favicon.ico">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
14.5 性能优化
解码像素大小
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri("large_image.jpg");
bitmap.DecodePixelWidth = 800; // 限制解码宽度
bitmap.DecodePixelHeight = 600; // 限制解码高度
bitmap.EndInit();
imageControl.Source = bitmap;
缓存选项
bitmap.CacheOption = BitmapCacheOption.OnLoad; // 立即加载并缓存,可以防止锁定图像
15.GroupBox分组
GroupBox 是 WPF 中用于将相关控件分组并提供视觉分隔的容器控件,继承自 System.Windows.Controls.HeaderedContentControl
15.1 基本概念与特性
核心特点
- 分组容器:将相关控件组织在一起
- 标题显示:带有可自定义的标题区域
- 视觉分隔:提供边框和背景区分不同组
- 布局控制:作为内容控件,可包含任意子元素
- 键盘导航:支持通过标题快速导航到内容。按下Tab键后,优先导航到GroupBox,之后方向键选择可以聚焦的内容。
与类似控件对比
|特性 |GroupBox |Expander |TabControl| Border| |-|-|-|-|-| |标题 |有 |有 |有(标签页)| 无| |折叠功能 |无 |有 |无 |无| |边框 |有 |有 |有 |有| |内容切换| 无 |展开/折叠 |标签页切换 |无|
15.2 基本使用
简单 GroupBox
<GroupBox Header="用户信息">
<StackPanel>
<TextBox Margin="5" Text="姓名"/>
<TextBox Margin="5" Text="年龄"/>
</StackPanel>
</GroupBox>
带复杂标题
<GroupBox>
<GroupBox.Header>
<StackPanel Orientation="Horizontal">
<Image Source="user.png" Width="16"/>
<TextBlock Text="用户信息" Margin="5,0"/>
</StackPanel>
</GroupBox.Header>
<!-- 内容 -->
</GroupBox>
15.3 核心属性
标题相关
- Header:标题内容(字符串或任意对象)
- HeaderTemplate:标题内容的数据模板
外观属性
- BorderBrush:边框颜色
- BorderThickness:边框粗细
- Background:背景色
- Foreground:前景色(影响标题文本)
- Padding:内边距
行为属性
- IsEnabled:是否启用(禁用时内容也会禁用)
- Focusable:是否可获取焦点
- HorizontalContentAlignment:内容水平对齐
- VerticalContentAlignment:内容垂直对齐
16.ScrollViewer 滚动视图
功能:内容滚动容器,当内容超出可视区域时提供滚动条
继承关系:ContentControl → Control → FrameworkElement → UIElement
典型用途:显示大型内容、长列表、图片查看器等
基本用法:
<Window x:Class="TestWpfApp.MainWindow"
Title="MainWindow" Height="400" Width="350">
<Grid>
<Border Width="180" Height="180" BorderBrush="Black" BorderThickness="1">
<!--HorizontalScrollBarVisibility:水平滚动条的可见性
VerticalScrollBarVisibility:垂直滚动条的可见性
ScrollChanged:滚动条的变化事件-->
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid Width="160" Height="200" Background="Red"/>
</ScrollViewer>
</Border>
</Grid>
</Window>
核心属性:
| 属性 | 说明 | 常用值 |
|---|---|---|
| VerticalScrollBarVisibility | 垂直滚动条可见性 | Auto, Visible, Hidden, Disabled |
| HorizontalScrollBarVisibility | 水平滚动条可见性 | 同上 |
| CanContentScroll | 启用逻辑滚动(虚拟化) | true/false |
| IsDeferredScrollingEnabled | 延迟滚动(性能优化) | true/false |
| PanningMode | 触摸屏滚动模式 | None, VerticalOnly, HorizontalOnly, Both |
常用方法
// 滚动控制
ScrollToVerticalOffset(double offset) // 垂直滚动到指定位置
ScrollToHorizontalOffset(double offset) // 水平滚动到指定位置
ScrollToEnd() // 滚动到底部
ScrollToHome() // 滚动到顶部
LineUp()/LineDown() // 单行滚动
PageUp()/PageDown() // 整页滚动
17.ScrollBar 滚动条
功能:独立的滚动条控件,用于控制内容滚动位置
继承关系:RangeBase → Control → FrameworkElement → UIElement
与ScrollViewer关系:ScrollViewer内部使用两个ScrollBar实现滚动
18.Slider 滑块
18.1 基本概念与特性
核心特点:
- 范围选择:允许用户在最小值和最大值之间选择数值
- 方向灵活:支持水平和垂直两种布局方向
- 精度控制:通过TickFrequency和IsSnapToTickEnabled实现精确取值
- 可视化标记:支持刻度线(Tick)显示
- 丰富交互:支持鼠标、键盘和触摸操作 继承关系:
Slider → RangeBase → Control → FrameworkElement → UIElement
18.2 基本使用
<!-- 水平滑块 -->
<Slider Minimum="0" Maximum="100" Value="50"/>
<!-- 垂直滑块 -->
<Slider Orientation="Vertical" Minimum="0" Maximum="1" Value="0.5" Height="100"/>
<Slider Minimum="0" Maximum="100" Value="50" SmallChange="1" LargeChange="10"
TickPlacement="BottomRight" IsSnapToTickEnabled="True"
IsMoveToPointEnabled="True" TickFrequency="1"
AutoToolTipPlacement="BottomRight" AutoToolTipPrecision="1"/>

18.3 核心属性
值范围属性
| 属性 | 说明 | 默认值 |
|---|---|---|
| Minimum | 最小值 | 0 |
| Maximum | 最大值 | 10 |
| Value | 当前值 | 0 |
| SmallChange | 小步长变化量 | 0.1 |
| LargeChange | 大步长变化量 | 1 |
外观属性
| 属性 | 说明 |
|---|---|
| Orientation | 方向(Horizontal/Vertical) |
| TickPlacement | 刻度线位置(None/TopLeft/BottomRight/Both) |
| TickFrequency | 刻度间隔频率 |
| IsDirectionReversed | 是否反转方向 |
| AutoToolTipPlacement | 工具提示位置 |
| AutoToolTipPrecision | 工具提示小数位数 |
行为属性
| 属性 | 说明 |
|---|---|
| IsSnapToTickEnabled | 是否吸附到刻度 |
| IsMoveToPointEnabled | 点击轨道是否直接跳转 |
| Delay | 重复按钮延迟时间(ms) |
| Interval | 重复按钮间隔时间(ms) |
19.ProgressBar进度条
ProgressBar(进度条)是 WPF 中用于显示操作进度的控件,它能够直观地展示任务的完成情况。
19.1 基本使用
基本声明
<!-- 确定进度模式 -->
<ProgressBar Minimum="0" Maximum="100" Value="50" Height="20"/>
<!-- 不确定进度模式 -->
<ProgressBar IsIndeterminate="True" Height="20"/>
19.2 核心属性
进度控制属性
| 属性 | 说明 | 默认值 |
|---|---|---|
| Minimum | 最小值 | 0 |
| Maximum | 最大值 | 100 |
| Value | 当前进度值 | 0 |
| IsIndeterminate | 是否为不确定模式 | false |
外观属性
| 属性 | 说明 |
|---|---|
| Orientation | 方向(Horizontal/Vertical) |
| Foreground | 进度条填充色 |
| Background | 进度条背景色 |
| BorderBrush | 边框颜色 |
| BorderThickness | 边框粗细 |
行为属性
| 属性 | 说明 |
|---|---|
| IsEnabled | 是否启用 |
| Visibility | 可见性 |
19.3 圆角进度条
<ProgressBar>
<ProgressBar.Template>
<ControlTemplate TargetType="ProgressBar">
<Grid>
<Border CornerRadius="5" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
<Border CornerRadius="5" Name="PART_Track">
<Rectangle Name="PART_Indicator"
Fill="{TemplateBinding Foreground}"
HorizontalAlignment="Left"/>
</Border>
</Grid>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>

20.Calendar日历
提供日期选择功能的可视化日历控件
基本使用
<Calendar
DisplayDate="2025-5-5"
DisplayDateStart="2025-1-1"
DisplayDateEnd="2025-5-5"
SelectionMode="SingleDate"
FirstDayOfWeek="Monday"/>

核心属性
| 属性 | 说明 | 常用值 |
|---|---|---|
| SelectedDate | 选中的日期 | DateTime对象 |
| SelectedDates | 多个选中日期集合 | DateTime集合 |
| DisplayDate | 当前显示的月份 | DateTime对象 |
| DisplayDateStart | 可显示的最早日期 | DateTime对象 |
| DisplayDateEnd | 可显示的最晚日期 | DateTime对象 |
| SelectionMode | 选择模式 | SingleDate, SingleRange, MultipleRange, None |
| FirstDayOfWeek | 每周的第一天 | Sunday, Monday等DayOfWeek枚举值 |
| IsTodayHighlighted | 是否高亮今天 | true/false |
| BlackoutDates | 不可选日期集合 | CalendarDateRange集合 |
常用方法
// 添加不可选日期
calendar.BlackoutDates.Add(new CalendarDateRange(startDate, endDate));
// 清除所有选择
calendar.SelectedDates.Clear();
// 导航到特定月份
calendar.DisplayDate = new DateTime(2023, 7, 1);
事件处理
|事件 |触发时机| |-|-| |SelectedDatesChanged |选中日期变化时| |DisplayDateChanged |显示月份变化时|
calendar.SelectedDatesChanged += (sender, e) => {
var selectedDates = ((Calendar)sender).SelectedDates;
// 处理选中日期
};
21.DatePicker日期选择
提供日期选择功能的输入控件
使用
<DatePicker
SelectedDate="{Binding SelectedDate}"
DisplayDateStart="2025-01-01"
DisplayDateEnd="2025-12-31"
FirstDayOfWeek="Monday"
IsTodayHighlighted="True"
Text="选择日期"/>
核心属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| SelectedDate | 选中的日期 | DateTime? null | |
| DisplayDate | 日历打开时显示的日期 | DateTime | 当前日期 |
| DisplayDateStart | 可选择的最早日期 | DateTime? | null |
| DisplayDateEnd | 可选择的最晚日期 | DateTime? | null |
| FirstDayOfWeek | 每周的第一天 | DayOfWeek | CurrentCulture |
| IsTodayHighlighted | 是否高亮今天 | bool | true |
| SelectedDateFormat | 日期显示格式 | DatePickerFormat | Short |
| Text | 文本框显示的文本 | string | "" |
| IsDropDownOpen | 日历是否展开 | bool | false |
| BlackoutDates | 不可选日期集合 | CalendarBlackoutDatesCollection | 空 |
常用方法
// 清空选择
datePicker.SelectedDate = null;
// 添加不可选日期
datePicker.BlackoutDates.Add(new CalendarDateRange(startDate, endDate));
// 获取格式化文本
string dateString = datePicker.Text;
事件处理
| 事件 | 触发时机 |
|---|---|
| SelectedDateChanged | 选中日期变化时 |
| DateValidationError | 日期验证失败时 |
| CalendarOpened | 日历展开时 |
| CalendarClosed | 日历关闭时 |
22.MediaElement媒体播放
<MediaElement x:Name="mediaPlayer"
Source="media/sample.mp4"
LoadedBehavior="Manual"
UnloadedBehavior="Stop"
Volume="0.5"/>
| 属性 | 说明 |
|---|---|
| Source | 媒体文件路径(URI格式) |
| LoadedBehavior | 加载后的行为(Play, Pause, Stop等) |
| Volume | 音量(0.0到1.0) |
| Balance | 声道平衡(-1.0左到1.0右) |
| SpeedRatio | 播放速度(1.0正常速度) |
| IsMuted | 是否静音 |
| NaturalDuration | 媒体总时长(只读) |
| Position | 当前播放位置 |
播放控制实现
// 播放
mediaPlayer.Play();
// 暂停
mediaPlayer.Pause();
// 停止
mediaPlayer.Stop();
// 定位
mediaPlayer.Position = TimeSpan.FromSeconds(30);
23.Expander 折叠控件
可展开/折叠的内容容器,带有标题和切换按钮
<Expander Header="详细信息">
<TextBlock Text="这里是可展开的详细内容..." Padding="10"/>
</Expander>
<Expander
Header="高级选项"
IsExpanded="False"
ExpandDirection="Down"
Padding="5">
<!-- 内容 -->
</Expander>
核心属性
| 属性 | 说明 | 常用值 |
|---|---|---|
| IsExpanded | 是否展开 | true/false |
| ExpandDirection | 展开方向 | Down, Up, Left, Right |
| Header | 标题内容 | 字符串或任意UI元素 |
| HeaderTemplate | 标题模板 | DataTemplate |
| Content | 展开的内容 | 任意UI元素 |
事件处理
| 事件 | 触发时机 |
|---|---|
| Expanded | 展开时触发 |
| Collapsed | 折叠时触发 |
五.集合控件
1.ListBox 列表
ListBox 是 WPF 中最常用的列表控件之一,它提供了丰富的数据展示和交互功能
1.1 重要属性
选择相关属性
- SelectedItem - 当前选中的项
- SelectedIndex - 当前选中项的索引
- SelectedValue - 当使用 SelectedValuePath 时获取的值
- SelectedValuePath - 指定从选中项中提取哪个属性作为 SelectedValue
- SelectionMode - 选择模式(Single-单选,Multiple-多选,Extended-扩展选择)
显示相关属性
- ItemsSource - 数据源绑定
- DisplayMemberPath - 指定显示项的哪个属性
- ItemTemplate - 自定义项的显示模板
- ItemContainerStyle - 项的容器样式
- ScrollViewer.VerticalScrollBarVisibility - 滚动条可见性
1.2 事件处理
- SelectionChanged - 选择项变化时触发
- MouseDoubleClick - 双击项时触发
1.3 虚拟化
对于大量数据,可以使用虚拟化提高性能
<ListBox VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"/>
1.4 使用
14.1 简单使用
从下面选项中选择一项或者多项
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="选择:"/>
<TextBlock x:Name="selItemValue"/>
</StackPanel>
<ListBox x:Name="listBox" SelectionMode="Single" SelectedIndex="1" SelectionChanged="ListBox_SelectionChanged">
<ListBoxItem Content="语文"/>
<ListBoxItem Content="数学"/>
<ListBoxItem Content="英语"/>
<ListBoxItem Content="物理"/>
<ListBoxItem Content="化学"/>
<ListBoxItem Content="生物"/>
</ListBox>
</StackPanel>
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(sender is ListBox listBox)
{
if (listBox.SelectedItem is ListBoxItem item)
{
selItemValue.Text = item.Content.ToString();
}
}
}

14.2 代码添加数据
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="选择:"/>
<TextBlock x:Name="selItemValue"/>
</StackPanel>
<ListBox x:Name="listBox" SelectionMode="Single" SelectedIndex="1" SelectionChanged="ListBox_SelectionChanged">
</ListBox>
</StackPanel>
public MainWindow()
{
InitializeComponent();
List<string> list = new List<string>();
list.Add("语文");
list.Add("数学");
list.Add("英语");
list.Add("物理");
list.Add("化学");
list.Add("生物");
listBox.ItemsSource = list;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(sender is ListBox listBox)
{
if (listBox.SelectedItem is ListBoxItem item)
{
selItemValue.Text = item.Content.ToString();
}
}
}
14.3 使用对象作为数据项
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="选择:"/>
<TextBlock x:Name="selItemValue"/>
</StackPanel>
<ListBox x:Name="listBox" DisplayMemberPath="Name" SelectedValuePath="Name"
SelectionMode="Single" SelectedIndex="1" SelectionChanged="ListBox_SelectionChanged">
</ListBox>
</StackPanel>
public MainWindow()
{
InitializeComponent();
List<Subject> list = new List<Subject>();
list.Add(new Subject() { Index=0,Name= "语文" });
list.Add(new Subject() { Index=1,Name= "数学" });
list.Add(new Subject() { Index=2,Name= "英语" });
listBox.ItemsSource = list;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(sender is ListBox listBox)
{
if (listBox.SelectedItem is Subject item)
{
selItemValue.Text = item.Name;
}
}
}
class Subject
{
public int Index { get; set; }
public string Name { get; set; }
}
14.4 处理数据源变更
数据源变更包括删除、增加项以及修改项。
错误变更数据源案例:
public partial class MainWindow : Window
{
private Subject selSubject = null;
private List<Subject> list = new List<Subject>();
public MainWindow()
{
InitializeComponent();
list.Add(new Subject() { Index=0,Name= "语文" });
list.Add(new Subject() { Index=1,Name= "数学" });
list.Add(new Subject() { Index=2,Name= "英语" });
listBox.ItemsSource = list;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(sender is ListBox listBox)
{
if (listBox.SelectedItem is Subject item)
{
selItemValue.Text = item.Name;
selSubject = item;
}
}
}
class Subject
{
public int Index { get; set; }
public string Name { get; set; }
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// 通过绑定的list进行删除是无法删除的
list.Remove(selSubject);
// 报错:当 ItemsSource 正在使用时操作无效
listBox.Items.Remove(selSubject);
}
}
正确变更数据源案例:
使用ObservableCollection集合,该集合数据变更时会进行通知更新。
public partial class MainWindow : Window
{
private Subject selSubject = null;
private ObservableCollection<Subject> list = new ObservableCollection<Subject>();
```
private void Button_Click(object sender, RoutedEventArgs e)
{
//
list.Remove(selSubject);
}
}
变更数据源某项属性案例:
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="选择:"/>
<TextBlock x:Name="selItemValue"/>
<Button Content="修改" Click="Button_Click"/>
</StackPanel>
<ListBox x:Name="listBox" DisplayMemberPath="Name" SelectedValuePath="Name" SelectionMode="Single" SelectedIndex="1" SelectionChanged="ListBox_SelectionChanged">
</ListBox>
</StackPanel>
public partial class MainWindow : Window
{
private Subject selSubject = null;
private ObservableCollection<Subject> list = new ObservableCollection<Subject>();
public MainWindow()
{
InitializeComponent();
list.Add(new Subject() { Index=0,Name= "语文" });
list.Add(new Subject() { Index=1,Name= "数学" });
list.Add(new Subject() { Index=2,Name= "英语" });
listBox.ItemsSource = list;
}
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(sender is ListBox listBox)
{
if (listBox.SelectedItem is Subject item)
{
selItemValue.Text = item.Name;
selSubject = item;
}
}
}
class Subject: INotifyPropertyChanged
{
private int _index;
public int Index
{
get { return _index; }
set { _index = value; OnPropertyChanged(nameof(Index)); }
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(nameof(Name)); }
}
public event PropertyChangedEventHandler PropertyChanged;
// 通知属性值改变
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (selSubject != null)
{
selSubject.Name = selSubject.Name + selSubject.Index;
}
}
}
1.5 自定义模板
<StackPanel Margin="10">
<StackPanel Orientation="Horizontal">
<TextBlock Text="选择:"/>
<TextBlock x:Name="selItemValue"/>
</StackPanel>
<ListBox x:Name="listBox" SelectedValuePath="Name" SelectionMode="Single" SelectedIndex="1" SelectionChanged="ListBox_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Index}"/>
<TextBlock Text="{Binding Name}" Margin="10,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>

2.ListView
ListView 是 WPF 中功能强大的列表控件,继承自 ListBox,但提供了更丰富的显示功能,特别是支持多列视图(类似表格)。
<StackPanel Margin="5">
<TextBlock Text="友情链接"/>
<ListView x:Name="listView">
<ListView.View>
<GridView>
<GridViewColumn Header="序号" Width="40" DisplayMemberBinding="{Binding Index}"/>
<GridViewColumn Header="Id" Width="50" DisplayMemberBinding="{Binding Id}"/>
<GridViewColumn Header="名称" Width="120" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Width="160" DisplayMemberBinding="{Binding Url}">
<GridViewColumnHeader>
<GridViewColumnHeader.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="/Views/web.png" Width="18" Height="18"/>
<TextBlock VerticalAlignment="Center" Text="网站" />
</StackPanel>
</DataTemplate>
</GridViewColumnHeader.ContentTemplate>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn Header="操作" Width="120">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="编辑"/>
<Button Content="删除" Margin="3,0,0,0"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</StackPanel>
public partial class MainWindow : Window
{
ObservableCollection<Blogroll> blogrolls = new ObservableCollection<Blogroll>();
public MainWindow()
{
InitializeComponent();
blogrolls.Add(new Blogroll
{
Index = 1,
Id = "web_01",
Name = "Google",
Url = "https://www.google.com"
});
blogrolls.Add(new Blogroll
{
Index = 2,
Id = "web_02",
Name = "Bing",
Url = "https://www.bing.com"
});
blogrolls.Add(new Blogroll
{
Index = 3,
Id = "web_03",
Name = "Yahoo",
Url = "https://www.yahoo.com"
});
blogrolls.Add(new Blogroll
{
Index = 4,
Id = "web_04",
Name = "DuckDuckGo",
Url = "https://www.duckduckgo.com"
});
listView.ItemsSource = blogrolls;
}
}
public class Blogroll : INotifyPropertyChanged
{
private int _index;
public int Index
{
get { return _index; }
set
{
if (_index != value)
{
_index = value;
OnPropertyChanged(nameof(Index));
}
}
}
private string _Id;
public string Id
{
get { return _Id; }
set
{
if (_Id != value)
{
_Id = value;
OnPropertyChanged(nameof(Id));
}
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
}
private string _url;
public string Url
{
get { return _url; }
set
{
if (_url != value)
{
_url = value;
OnPropertyChanged(nameof(Url));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

3.DataGrid
3.1 基础概念
DataGrid 简介:
WPF 中最强大的数据展示控件
提供类似 Excel 的表格功能
支持排序、编辑、验证等高级功能
继承自 ItemsControl,具有 ItemsSource 绑定能力 核心组件:
行(Row): 数据记录
列(Column): 数据字段
单元格(Cell): 行和列的交点
表头(Header): 列标题
行头(RowHeader): 行选择指示器
3.2 基本使用
基本语法:
<DataGrid x:Name="dataGrid">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
<DataGridTextColumn Header="姓名" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
数据绑定方式:
自动生成列
<DataGrid AutoGenerateColumns="True"/>
手动定义列
<DataGrid AutoGenerateColumns="False">
<!-- 列定义 -->
</DataGrid>
常用列类型:
| 列类型 | 描述 | 示例 |
|---|---|---|
| DataGridTextColumn | 文本列 | <DataGridTextColumn Binding="{Binding Name}"/> |
| DataGridCheckBoxColumn | 复选框列 | <DataGridCheckBoxColumn Binding="{Binding IsActive}"/> |
| DataGridComboBoxColumn | 下拉框列 | <DataGridComboBoxColumn ItemsSource="{Binding Departments}"/> |
| DataGridHyperlinkColumn | 超链接列 | <DataGridHyperlinkColumn Binding="{Binding Url}"/> |
| DataGridTemplateColumn | 自定义模板列 | 见高级用法 |
3.3 DataGrid 核心功能
排序功能:
<DataGrid CanUserSortColumns="True">
<DataGrid.Columns>
<DataGridTextColumn Header="日期"
Binding="{Binding Date}"
SortDirection="Descending"/>
</DataGrid.Columns>
</DataGrid>
编辑功能:
<DataGrid CanUserAddRows="True" <!-- 允许添加行 -->
CanUserDeleteRows="True" <!-- 允许删除行 -->
CanUserEditRows="True"> <!-- 允许编辑行 -->
</DataGrid>
选择模式:
<DataGrid SelectionMode="Extended" <!-- 多选模式 -->
SelectionUnit="FullRow"> <!-- 整行选择 -->
</DataGrid>
行详细信息:
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Description}"/>
<Image Source="{Binding ImagePath}"/>
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
<!--VisibleWhenSelected:只有当行被选中时才显示详细信息
Visible:始终显示详细信息
Collapsed:从不显示详细信息-->
<DataGrid.RowDetailsVisibilityMode>VisibleWhenSelected</DataGrid.RowDetailsVisibilityMode>
3.4 DataGrid 高级功能
自定义列模板
<DataGridTemplateColumn Header="操作">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="编辑" Command="{Binding EditCommand}"/>
<Button Content="删除" Command="{Binding DeleteCommand}"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
分组显示
<DataGrid>
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
3.5 DataGrid 样式与模板
行样式
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="LightYellow"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
交替行颜色
<DataGrid AlternationCount="2"
AlternatingRowBackground="LightGray"/>
单元格样式
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
3.6 DataGrid 性能优化
虚拟化技术
<DataGrid EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingPanel.VirtualizationMode="Recycling"/>
冻结列
<DataGrid FrozenColumnCount="2"> <!-- 冻结前两列 -->
</DataGrid>
延迟滚动
<DataGrid ScrollViewer.IsDeferredScrollingEnabled="True"/>
3.7 常见问题
3.7.1 自动生成列自定义
private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
// 修改列标题
if (e.PropertyName == "FirstName")
e.Column.Header = "名";
// 隐藏某些列
if (e.PropertyName == "SecretProperty")
e.Cancel = true;
// 自定义日期格式
if (e.PropertyType == typeof(DateTime))
(e.Column as DataGridTextColumn).Binding.StringFormat = "yyyy-MM-dd";
}
3.7.2 大数据量处理
<DataGrid VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
ScrollViewer.IsDeferredScrollingEnabled="True"/>
3.7.3 行双击事件
<DataGrid MouseDoubleClick="DataGrid_MouseDoubleClick"/>
3.7.4 可编辑数据表格
<DataGrid ItemsSource="{Binding Products}"
CanUserAddRows="True"
CanUserDeleteRows="True"
CellEditEnding="DataGrid_CellEditEnding">
<DataGrid.Columns>
<DataGridTextColumn Header="名称" Binding="{Binding Name}"/>
<DataGridTextColumn Header="价格" Binding="{Binding Price}"/>
</DataGrid.Columns>
</DataGrid>
private void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
// 验证编辑内容
if (e.Column.Header.ToString() == "价格")
{
var newValue = (e.EditingElement as TextBox)?.Text;
if (!decimal.TryParse(newValue, out _))
{
e.Cancel = true;
MessageBox.Show("请输入有效的价格");
}
}
}
3.8 综合案例
xml:
样式在后期,这里先使用
<Window x:Class="TestWpfApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWpfApp"
xmlns:controls="clr-namespace:TestWpfApp.Controls"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="850">
<Window.Resources>
<!-- 颜色定义 -->
<Color x:Key="PrimaryColor">#FF4285F4</Color>
<Color x:Key="HoverColor">#FFE8F0FE</Color>
<Color x:Key="SelectedColor">#FFD2E3FC</Color>
<Color x:Key="HeaderColor">#F5F5F5</Color>
<Color x:Key="BorderColor">#FFE0E0E0</Color>
<!-- 转换为SolidColorBrush -->
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource PrimaryColor}"/>
<SolidColorBrush x:Key="HoverBrush" Color="{StaticResource HoverColor}"/>
<SolidColorBrush x:Key="SelectedBrush" Color="{StaticResource SelectedColor}"/>
<SolidColorBrush x:Key="HeaderBrush" Color="{StaticResource HeaderColor}"/>
<SolidColorBrush x:Key="BorderBrush" Color="{StaticResource BorderColor}"/>
<!-- 按钮样式 -->
<Style x:Key="FlatButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PrimaryBrush}"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1"
CornerRadius="2">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource HoverBrush}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- DataGrid 整体样式 -->
<Style TargetType="DataGrid">
<Setter Property="Background" Value="White"/>
<Setter Property="Foreground" Value="#333333"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="True"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="HeadersVisibility" Value="Column"/>
<Setter Property="SelectionUnit" Value="FullRow"/>
<Setter Property="CanUserResizeRows" Value="False"/>
<Setter Property="ColumnHeaderHeight" Value="32"/>
<Setter Property="RowHeight" Value="32"/>
<Setter Property="GridLinesVisibility" Value="None"/>
<Setter Property="FontSize" Value="14"/>
</Style>
<!-- DataGrid 列标题样式 -->
<Style TargetType="DataGridColumnHeader">
<Setter Property="Background" Value="{StaticResource HeaderBrush}"/>
<Setter Property="Foreground" Value="#333333"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="Padding" Value="10,0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Height" Value="32"/>
</Style>
<!-- DataGrid 行样式 -->
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource HoverBrush}"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource PrimaryBrush}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Background" Value="{StaticResource SelectedBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- DataGrid 单元格样式 -->
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Padding" Value="10,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="#333333"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- 操作列按钮样式 -->
<Style TargetType="Button" BasedOn="{StaticResource FlatButtonStyle}">
<Setter Property="Width" Value="60"/>
<Setter Property="Height" Value="24"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<!-- 标题文本样式 -->
<Style TargetType="TextBlock" x:Key="TitleStyle">
<Setter Property="FontSize" Value="18"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="{StaticResource PrimaryBrush}"/>
<Setter Property="Margin" Value="0,0,0,10"/>
</Style>
<!-- 提示文本样式 -->
<Style TargetType="TextBlock" x:Key="HintStyle">
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="#666666"/>
<Setter Property="Margin" Value="0,0,0,10"/>
</Style>
</Window.Resources>
<Grid>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 应用标题样式 -->
<TextBlock Text="用户管理系统" Style="{StaticResource TitleStyle}"/>
<!-- 应用提示样式 -->
<TextBlock Grid.Row="1" Text="操作提示:双击编辑,Del删除该用户,底部空白行添加用户"
Style="{StaticResource HintStyle}"/>
<!-- DataGrid 应用样式 -->
<DataGrid x:Name="dataGrid" Grid.Row="2"
VirtualizingPanel.ScrollUnit="Item"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
ScrollViewer.IsDeferredScrollingEnabled="True"
AutoGenerateColumns="False"
CanUserDeleteRows="True" CanUserSortColumns="True"
CanUserResizeColumns="False" CanUserAddRows="True">
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="选择" Binding="{Binding IsSelect}" Width="50"/>
<DataGridTextColumn Header="ID" Binding="{Binding Id}" Width="60"/>
<DataGridTextColumn Header="账号" Binding="{Binding Username}" Width="120"/>
<DataGridTextColumn Header="电话" Binding="{Binding Phone}" Width="120"/>
<DataGridComboBoxColumn x:Name="dataGridGender" Header="性别"
SelectedItemBinding="{Binding Gender}" Width="80"/>
<DataGridHyperlinkColumn Header="链接" Binding="{Binding Link}" Width="120">
<DataGridHyperlinkColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextDecorations" Value="Underline"/>
<Setter Property="Foreground" Value="{StaticResource PrimaryBrush}"/>
</Style>
</DataGridHyperlinkColumn.ElementStyle>
</DataGridHyperlinkColumn>
<DataGridTextColumn Width="*" Header="备注" Binding="{Binding Remark}"/>
<DataGridTemplateColumn Header="操作" Width="140">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Content="编辑" Command="{Binding EditCommand}"/>
<Button Content="删除" Command="{Binding DeleteCommand}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="/Views/web.png" Width="20" Height="20"/>
<TextBlock Text="当前行的详细信息" VerticalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
<DataGrid.RowDetailsVisibilityMode>VisibleWhenSelected</DataGrid.RowDetailsVisibilityMode>
</DataGrid>
</Grid>
</Grid>
</Window>
c#
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace TestWpfApp
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
private readonly ObservableCollection<User> users = new ObservableCollection<User>();
public MainWindow()
{
InitializeComponent();
dataGrid.ItemsSource = users;
dataGridGender.ItemsSource = Enum.GetValues(typeof(GenderType));
for (int i = 0; i < 1000; i++)
{
users.Add(new User
{
Username = "Username" + i,
Link = "https://www.diandiandidi.club",
Phone = "133****6666",
Remark = "Remark" + i,
});
}
}
}
public class User : INotifyPropertyChanged
{
private bool _isSelect;
public bool IsSelect
{
get { return _isSelect; }
set
{
if (_isSelect != value)
{
_isSelect = value;
OnPropertyChanged(nameof(IsSelect));
}
}
}
private int _id;
public int Id
{
get { return _id; }
set
{
if (_id != value)
{
_id = value;
OnPropertyChanged(nameof(Id));
}
}
}
private string _phone;
public string Phone
{
get { return _phone; }
set
{
if (_phone != value)
{
_phone = value;
OnPropertyChanged(nameof(Phone));
}
}
}
private string _username;
public string Username
{
get { return _username; }
set
{
if (_username != value)
{
_username = value;
OnPropertyChanged(nameof(Username));
}
}
}
private GenderType _gender=GenderType.未知;
public GenderType Gender
{
get { return _gender; }
set
{
if(value != _gender)
{
_gender = value;
OnPropertyChanged(nameof(Gender));
}
}
}
private string _link;
public string Link
{
get { return _link; }
set
{
if (_link != value)
{
_link = value;
OnPropertyChanged(nameof(Link));
}
}
}
private string _remark;
public string Remark
{
get { return _remark; }
set
{
if (_remark != value)
{
_remark = value;
OnPropertyChanged(nameof(Remark));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public enum GenderType
{
男, 女, 未知
}
}
效果:

4.ComboBox 下拉列表
下拉选择控件,继承自 ItemsControl,结合了文本框和下拉列表的功能,支持单选、数据绑定、自定义项模板等特性。
4.1 核心组成部分
- 下拉按钮:触发下拉列表
- 选择框:显示当前选中项
- 下拉列表:包含所有可选项目
- 项模板:定义每个选项的显示方式
4.2 基本用法
静态项定义
<ComboBox>
<ComboBoxItem>选项1</ComboBoxItem>
<ComboBoxItem>选项2</ComboBoxItem>
<ComboBoxItem>选项3</ComboBoxItem>
</ComboBox>
数据绑定方式
<ComboBox DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding SelectedId}"/>
4.3 核心属性
| 属性 | 描述 | 示例 |
|---|---|---|
| ItemsSource | 数据源绑定 | ItemsSource="{Binding Products}" |
| DisplayMemberPath | 显示文本的属性 | DisplayMemberPath="ProductName" |
| SelectedValuePath | 选中项的值属性 | SelectedValuePath="ProductId" |
| SelectedItem | 当前选中项对象 | SelectedItem="{Binding SelectedProduct}" |
| SelectedValue | 当前选中项的值 | SelectedValue="{Binding SelectedProductId}" |
| SelectedIndex | 当前选中项的索引 | SelectedIndex="0" |
| IsEditable | 是否可编辑 | IsEditable="True" |
| MaxDropDownHeight | 下拉列表最大高度 | MaxDropDownHeight="200" |
4.4 事件处理
|事件| 描述| |-|-| |SelectionChanged |选中项变化时触发| |DropDownOpened |下拉列表打开时触发| |DropDownClosed |下拉列表关闭时触发| |PreviewKeyDown| 键盘按键按下时触发|
4.5 案例-搜索下拉
<ComboBox x:Name="comboBox" SelectedValuePath="Name"
DisplayMemberPath="Name" DropDownOpened="ComboBox_DropDownOpened"
PreviewKeyUp="ComboBox_PreviewKeyUp"
IsEditable="True" IsTextSearchEnabled="False" Width="200" Height="30"/>

public partial class TestWindow : Window
{
ObservableCollection<User> searUsers = new ObservableCollection<User>();
List<User> allUsers = new List<User>();
public TestWindow()
{
InitializeComponent();
for (int i = 0; i < 100; i++)
{
allUsers.Add(new User() { Name = "Name" + i, Age = "Age" + i, Address = "Address" + i });
}
comboBox.ItemsSource = searUsers;
}
private void ComboBox_PreviewKeyUp(object sender, KeyEventArgs e)
{
searUsers.Clear();
int count = 0;
for (int i = 0; i < allUsers.Count; i++)
{
var item = allUsers[i];
if (item.Name.ToLower().Contains(comboBox.Text.ToLower()) || item.Age.Contains(comboBox.Text) || item.Address.Contains(comboBox.Text))
{
searUsers.Add(item);
count++;
if (count >= 10)
{
break;
}
}
}
comboBox.IsDropDownOpen = true;
}
private void ComboBox_DropDownOpened(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(comboBox.Text))
{
searUsers.Clear();
for (int i = 0; i < allUsers.Count&&i<10; i++)
{
searUsers.Add(allUsers[i]);
}
}
}
}
public class User : INotifyPropertyChanged
{
public string Name { get; set; }
public string Age { get; set; }
public string Address { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

5.TabControl 选项卡
- 选项卡式界面容器控件
- 继承自 Selector 类,允许用户通过选项卡切换不同内容
- 每个选项卡包含一个 TabItem 作为容器
5.1 基本用法
<TabControl>
<TabItem Header="首页">
<TextBlock Text="欢迎来到首页"/>
</TabItem>
<TabItem Header="设置">
<StackPanel>
<CheckBox Content="启用通知"/>
<Slider Maximum="100"/>
</StackPanel>
</TabItem>
</TabControl>

数据绑定方式
<TabControl SelectedIndex="0">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<ContentControl Content="{Binding Content}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
5.2 核心属性
|属性| 描述| |ItemsSource| 数据源绑定| |SelectedIndex |当前选中选项卡索引| |SelectedItem |当前选中选项卡项| |TabStripPlacement|选项卡位置| |ContentTemplate| 内容模板| |ItemTemplate |选项卡标题模板| |sSynchronizedWithCurrentItem |同步当前项|
5.3 TabItem
| 属性 | 描述 | 示例 |
|---|---|---|
| Header | 选项卡标题 | Header="设置" |
| HeaderTemplate | 标题模板 | |
| IsSelected | 是否选中 | IsSelected="True" |
| Content | 选项卡内容 |
5.4 动态添加/移除选项卡
// 添加选项卡
var newTab = new TabItem { Header = "新标签", Content = new UserControl1() };
tabControl.Items.Add(newTab);
// 移除当前选项卡
tabControl.Items.Remove(tabControl.SelectedItem);
5.5 选项卡位置控制
<TabControl TabStripPlacement="Left">
<!-- 选项卡将显示在左侧 -->
</TabControl>
可选值:Top(默认)、Bottom、Left、Right
5.6 案例-左侧导航
<TabControl TabStripPlacement="Left">
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="/Resources/Images/icon_shouye.png" Width="26" Height="26"/>
<TextBlock Text="首页" VerticalAlignment="Center" Margin="5,0,0,0" FontSize="16"/>
</StackPanel>
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Text="这里是首页" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</TabItem.Content>
</TabItem>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Source="/Resources/Images/icon_kandian.png" Width="26" Height="26"/>
<TextBlock Text="看点" VerticalAlignment="Center" Margin="5,0,0,0" FontSize="16"/>
</StackPanel>
</TabItem.Header>
<TabItem.Content>
<Grid>
<TextBlock Text="这里是看点" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</TabItem.Content>
</TabItem>
······
</TabControl>

6.TreeView 树形控件
6.1 TreeView 基础概念
TreeView 简介
- 层次结构数据展示控件
- 继承自 ItemsControl 类
- 支持节点展开/折叠、选择、编辑等操作
- 典型应用:文件浏览器、组织结构图、分类目录
核心组成部分
- TreeViewItem:树节点项
- HierarchicalDataTemplate:层级数据模板
- 展开/折叠按钮:控制子项显示
- 节点选择:单选/多选支持
6.2 基本用法
<TreeView>
<TreeViewItem Header="部门">
<TreeViewItem Header="研发部"/>
<TreeViewItem Header="市场部">
<TreeViewItem Header="北方区"/>
<TreeViewItem Header="南方区"/>
</TreeViewItem>
</TreeViewItem>
</TreeView>

6.3 核心属性
| 属性 | 描述 | 示例 |
|---|---|---|
| ItemsSource | 数据源绑定 | 后期mvvm讲解 |
| SelectedItem | 当前选中项 | SelectedItem="{Binding SelectedNode}" |
| SelectedValue | 选中项的值 | SelectedValue="{Binding SelectedId}" |
| SelectedValuePath | 值路径 | SelectedValuePath="Id" |
| ItemTemplate | 项模板 | 见模板部分 |
| BorderThickness | 边框粗细 | BorderThickness="1" |
| AllowDrop | 允许拖放 | AllowDrop="True" |
6.4 TreeViewItem 属性
| 属性 | 描述 | 示例 |
|---|---|---|
| Header | 节点标题 | Header="研发部" |
| IsExpanded | 是否展开 | IsExpanded="True" |
| IsSelected | 是否选中 | IsSelected="True" |
| ItemsSource | 子项数据源 | ItemsSource="{Binding Children}" |
6.5 案例-Html文档大纲查看
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="36"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="Html文件大纲" FontSize="16" FontWeight="Bold"/>
<Grid Grid.Row="1" Margin="0,5,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox x:Name="htmlFilePathTextBox" IsReadOnly="True" VerticalContentAlignment="Center" Padding="5,0">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Text" Value="点击按钮打开html文件..."/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Text" Value=""/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Button Grid.Column="1" Click="OpenHtmlFile_Click" Content="打开" Margin="5,0,0,0" Width="75"/>
</Grid>
<TreeView x:Name="treeView" Grid.Row="2" Margin="0,5,0,0">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:HtmlHeadingNode}"
ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Title}" FontWeight="Bold"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Grid>
public partial class TestWindow : Window
{
private ObservableCollection<HtmlHeadingNode> headingNodes = new ObservableCollection<HtmlHeadingNode>();
public TestWindow()
{
InitializeComponent();
treeView.ItemsSource = headingNodes;
}
private void OpenHtmlFile_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "HTML文件 (*.html;*.htm)|*.html;*.htm|所有文件 (*.*)|*.*";
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == true)
{
try
{
htmlFilePathTextBox.Text = openFileDialog.FileName;
string htmlContent = File.ReadAllText(htmlFilePathTextBox.Text);
headingNodes.Clear();
ParseHtmlHeadings(htmlContent);
}
catch (Exception ex)
{
MessageBox.Show($"读取文件时出错: {ex.Message}");
}
}
}
/// <summary>
/// 该代码由ai生成
/// </summary>
private void ParseHtmlHeadings(string htmlContent)
{
try
{
// 使用正则表达式匹配所有h1-h6标签
var regex = new Regex(@"<h([1-6])[^>]*>(.*?)<\/h[1-6]>", RegexOptions.IgnoreCase);
var matches = regex.Matches(htmlContent);
// 用于跟踪当前层级
Stack<HtmlHeadingNode> nodeStack = new Stack<HtmlHeadingNode>();
foreach (Match match in matches)
{
int level = int.Parse(match.Groups[1].Value);
string title = match.Groups[2].Value;
// 清理标题文本(移除HTML标签)
title = Regex.Replace(title, "<.*?>", string.Empty).Trim();
var newNode = new HtmlHeadingNode
{
Title = title,
Level = level
};
// 处理层级关系
while (nodeStack.Count > 0 && nodeStack.Peek().Level >= level)
{
nodeStack.Pop();
}
if (nodeStack.Count == 0)
{
headingNodes.Add(newNode);
}
else
{
nodeStack.Peek().Children.Add(newNode);
}
nodeStack.Push(newNode);
}
}
catch (Exception ex)
{
MessageBox.Show($"解析HTML标题时出错: {ex.Message}");
}
}
}
public class HtmlHeadingNode
{
public string Title { get; set; }
public int Level { get; set; }
public ObservableCollection<HtmlHeadingNode> Children { get; set; } = new ObservableCollection<HtmlHeadingNode>();
}

7.Menu 菜单
Menu(菜单)是WPF中用于构建应用程序导航系统的重要控件,主要作用包括:
1.提供命令访问入口:集中展示应用程序功能命令 2.组织功能分类:通过层级结构合理组织功能模块 3.节省界面空间:通过下拉/弹出方式隐藏非活动命令 4.标准化交互:遵循操作系统菜单交互规范 5.支持快捷键:提供键盘快捷操作方式
典型应用场景:
- 应用程序主菜单(顶部水平菜单)
- 上下文菜单(右键弹出菜单)
- 工具栏下拉菜单
- 导航菜单系统
7.1 Menu 控件的结构
逻辑结构:
Menu (根容器)
├── MenuItem (菜单项)
│ ├── MenuItem (子菜单项)
│ ├── Separator (分隔线)
│ └── ...更多子项
├── MenuItem
└── ...更多菜单项
视觉结构组成:
1.菜单栏:水平容器,承载顶级菜单项 2.菜单项:文本标签(Header),图标(Icon),快捷键提示(InputGestureText),子菜单箭头指示器 3.子菜单面板:弹出式容器,承载子菜单项 4.分隔线:视觉分组线(Separator)
7.2 核心属性
Menu 容器属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| ItemsSource | object | null | 数据绑定源 |
| ItemTemplate | DataTemplate | null | 菜单项模板 |
| Background | Brush | 系统色 | 背景色 |
| Foreground | Brush | 系统色 | 文字颜色 |
| IsMainMenu | bool | false | 是否作为主菜单(影响Alt键行为) |
MenuItem 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Header | object | null | 菜单项显示内容 |
| Command | ICommand | null | 关联命令 |
| CommandParameter | object | null | 命令参数 |
| InputGestureText | string | null | 快捷键提示文本 |
| Icon | object | null | 菜单项图标 |
| IsCheckable | bool | false | 是否可勾选 |
| IsChecked | bool | false | 是否已勾选 |
| StaysOpenOnClick | bool | false | 点击后是否保持菜单打开 |
| ItemsSource | IEnumerable | null | 子项数据源 |
7.3 重要事件
MenuItem 事件
| 事件 | 说明 |
|---|---|
| Click | 点击菜单项时触发 |
| Checked | 当IsCheckable=true且被勾选时触发 |
| Unchecked | 当IsCheckable=true且取消勾选时触发 |
| SubmenuOpened | 子菜单打开时触发 |
| SubmenuClosed | 子菜单关闭时触发 |
7.4 作为顶部菜单使用
<DockPanel>
<Menu DockPanel.Dock="Top" IsMainMenu="True">
<MenuItem Header="文件(_F)">
<MenuItem Header="新建(_N)" InputGestureText="Ctrl+N"/>
<MenuItem Header="打开(_O)" InputGestureText="Ctrl+O">
<MenuItem.Icon>
<Image Source="/Resources/Images/icon_folder.png" Width="20" Height="20"/>
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem Header="退出(_X)"/>
</MenuItem>
<MenuItem Header="编辑(_E)">
<MenuItem Header="撤销(_Z)" InputGestureText="Ctrl+Z"/>
<MenuItem Header="重做(_Y)" InputGestureText="Ctrl+Y"/>
</MenuItem>
<MenuItem Header="模式(_P)">
<MenuItem IsChecked="True" IsCheckable="True" Header="编辑(_E)" InputGestureText="Ctrl+E"/>
<MenuItem IsCheckable="True" Header="查看(_P)" InputGestureText="Ctrl+P"/>
</MenuItem>
</Menu>
<Grid DockPanel.Dock="Left" Width="100" Background="Orange"/>
<Grid DockPanel.Dock="Right" Width="100" Background="Green"/>
<Grid DockPanel.Dock="Bottom" Height="100" Background="Black"/>
<Grid/>
</DockPanel>

7.5 作为上下文菜单使用
在 WPF 中,几乎所有可视化控件都支持上下文菜单(ContextMenu),因为 ContextMenu 属性是定义在 FrameworkElement 基类中的。因此大多数控件均可以右键更多操作。
<ListBox>
<ListBoxItem Content="选项一"/>
<ListBoxItem Content="选项二"/>
<ListBoxItem Content="选项三"/>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="删除"/>
<MenuItem Header="详细"/>
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
8.StatusBar 状态栏
StatusBar(状态栏)是WPF中用于显示应用程序状态信息的控件。
主要作用包括:
1.状态信息展示:显示应用程序当前状态、进度、操作提示等 2.辅助信息呈现:展示光标位置、缩放比例、日期时间等辅助信息 3.操作反馈:提供长时间操作的进度反馈 4.系统信息显示:内存使用、网络状态等系统信息 5.用户引导:显示当前可执行操作的提示信息
典型应用场景:
- 文本编辑器的行列号显示
- 图像处理软件的缩放比例和颜色信息
- 数据库应用的连接状态
- 应用程序的进度指示
<DockPanel>
<Menu DockPanel.Dock="Top" IsMainMenu="True">
<MenuItem Header="文件(_F)"/>
<MenuItem Header="编辑(_E)"/>
<MenuItem Header="模式(_P)"/>
</Menu>
<Grid DockPanel.Dock="Bottom" Height="100" Background="CadetBlue">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StatusBar Grid.Row="1">
<StatusBarItem Content="版权所有©666 地址:xxxxx"/>
<StatusBarItem Content="版本:1.0.0"/>
<Separator/>
<StatusBarItem Content="状态:正常"/>
<ProgressBar Value="50" Width="200" Height="20" Margin="5,0,0,0"/>
</StatusBar>
</Grid>
<Grid DockPanel.Dock="Left" Width="100" Background="Orange"/>
<Grid DockPanel.Dock="Right" Width="100" Background="Green"/>
<Grid>
</Grid>
</DockPanel>

9.ToolBar 工具栏
ToolBar(工具栏)是WPF中用于快速访问常用命令的控件,它提供了一种紧凑且高效的方式来组织应用程序的功能按钮。
9.1 ToolBar 的作用和特点
主要作用
1.快速访问:提供对常用功能的快速访问 2.命令分组:将相关功能组织在一起 3.节省空间:通过溢出机制自动管理空间不足的情况 4.用户自定义:允许用户自定义工具栏内容和位置
核心特点
- 自动处理布局和溢出
- 支持分隔符和分组
- 可停靠在任何边缘
- 支持工具提示和快捷键
- 可自定义外观和行为
9.2 ToolBar 的基本结构
1.工具栏托盘(ToolBarTray):多个工具栏的容器 2.工具栏(ToolBar):单个工具栏容器 3.工具栏项:按钮、组合框等控件 4.溢出区域:空间不足时自动隐藏的项
9.3 核心属性和事件
ToolBarTray 属性
| 属性 | 说明 |
|---|---|
| Orientation | 排列方向(Horizontal/Vertical) |
| IsLocked | 是否锁定工具栏位置 |
ToolBar 属性
| 属性 | 说明 |
|---|---|
| Band | 指定工具栏所在的行/列 |
| BandIndex | 指定工具栏在行/列中的位置 |
| OverflowMode | 溢出行为(Always, Never, AsNeeded) |
| ToolTip | 工具栏提示 |
9.4 使用
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<Menu IsMainMenu="True">
<MenuItem Header="文件(_F)"/>
<MenuItem Header="编辑(_E)"/>
<MenuItem Header="模式(_P)"/>
</Menu>
<ToolBarTray>
<ToolBar>
<Button Content="新建"/>
<Button Content="打开"/>
<Button Content="保存"/>
<Separator/>
<Button Content="打印"/>
<Button Content="打印预览"/>
</ToolBar>
<ToolBar>
<Button Content="还原"/>
<Button Content="撤销"/>
</ToolBar>
</ToolBarTray>
</StackPanel>
<Grid DockPanel.Dock="Bottom" Height="100" Background="CadetBlue">
</Grid>
<Grid DockPanel.Dock="Left" Width="100" Background="Orange"/>
<Grid DockPanel.Dock="Right" Width="100" Background="Green"/>
<Grid>
</Grid>
</DockPanel>

六.图形控件
1.Shape 类
Shape 是所有 WPF 基本形状的抽象基类,提供了以下核心属性:
- Fill - 填充画刷
- Stroke - 边框画刷
- StrokeThickness - 边框粗细
- StrokeDashArray - 虚线样式
复杂场景:对于需要大量图形的场景,考虑使用 DrawingVisual 替代。
2.Ellipse 椭圆
Ellipse(椭圆)是 WPF 中用于绘制椭圆或圆形的基本形状控件
属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Width | double | 0 | 椭圆的宽度 |
| Height | double 0 | 椭圆的高度 | |
| Fill | Brush | null | 填充椭圆的画刷 |
| Stroke | Brush | null 椭圆边框的画刷 | |
| StrokeThickness | double | 1 | 边框粗细 |
| StrokeDashArray | DoubleCollection | null | 虚线样式 |
| Stretch | Stretch None | 填充模式 |
使用:
简单使用
<Ellipse Width="100" Height="100"
Fill="Blue" Stroke="Black"
StrokeThickness="2"/>

画刷
<Ellipse Width="120" Height="120">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="Yellow" Offset="0"/>
<GradientStop Color="Red" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
变换:
<Ellipse Width="60" Height="60" Fill="Purple">
<Ellipse.RenderTransform>
<TransformGroup>
<RotateTransform Angle="45"/>
<ScaleTransform ScaleX="1.5"/>
</TransformGroup>
</Ellipse.RenderTransform>
</Ellipse>

3.Line 线段
Line 是 WPF 中用于绘制直线的基本形状控件
属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| X1 | double | 0 | 起点X坐标 |
| Y1 | double | 0 | 起点Y坐标 |
| X2 | double | 0 | 终点X坐标 |
| Y2 | double | 0 | 终点Y坐标 |
| Stroke | Brush | null | 线条颜色 |
| StrokeThickness | double | 1 | 线条粗细 |
| StrokeStartLineCap | PenLineCap | Flat | 线条起点端帽样式 |
| StrokeEndLineCap | PenLineCap | Flat | 线条终点端帽样式 |
| StrokeDashArray | DoubleCollection | null | 虚线模式 |
| StrokeDashCap | PenLineCap | Flat | 虚线端点样式 |
| StrokeDashOffset | double | 0 | 虚线偏移量 |
使用:
<Line X1="10" Y1="10" X2="80" Y2="80" Stroke="Red" StrokeThickness="15"
StrokeStartLineCap="Round"
StrokeEndLineCap="Triangle"
StrokeDashArray="1,1"
StrokeDashCap="Triangle"
StrokeDashOffset="0"
/>

4.Rectangle 矩形
Rectangle(矩形)是 WPF 中用于绘制矩形或圆角矩形的基本形状控件
基本属性:
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Width | double | 0 | 矩形的宽度 |
| Height | double | 0 | 矩形的高度 |
| Fill | Brush | null | 矩形填充画刷 |
| Stroke | Brush | null | 矩形边框画刷 |
| StrokeThickness | double | 1 | 边框粗细 |
| RadiusX | double | 0 | 圆角X轴半径 |
| RadiusY | double | 0 | 圆角Y轴半径 |
| Stretch | Stretch | None | 填充模式 |
边框样式属性:
| 属性 | 说明 |
|---|---|
| StrokeDashArray | 虚线模式(如 "2,1" 表示2单位实线+1单位空白) |
| StrokeDashCap | 虚线端点样式(Flat, Round, Square, Triangle) |
| StrokeDashOffset | 虚线偏移量 |
| StrokeLineJoin | 边框连接处样式(Miter, Bevel, Round) |
| StrokeMiterLimit | 斜接长度限制 |
使用:
<Rectangle Canvas.Top="10" Canvas.Left="10"
StrokeThickness="3" RadiusX="10" RadiusY="10"
Width="200" Height="100" Fill="Red" Stroke="Blue"/>

<Rectangle Width="150" Height="100" Canvas.Left="20" Canvas.Top="20">
<!-- 线性渐变填充 -->
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0"/>
<GradientStop Color="Red" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
<!-- 虚线边框 -->
<Rectangle.Stroke>
<SolidColorBrush Color="DarkOrange"/>
</Rectangle.Stroke>
<Rectangle.StrokeDashArray>
<DoubleCollection>2,2</DoubleCollection>
</Rectangle.StrokeDashArray>
</Rectangle>

5.Polyline 折线
Polyline(多段线)是 WPF 中用于绘制由一系列相连直线段组成的形状控件
基本属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Points | PointCollection | null | 定义多段线各点的集合 |
| Fill | Brush | null | 多段线封闭区域的填充画刷 |
| Stroke | Brush | null | 多段线描边画刷 |
| StrokeThickness | double | 1 | 描边粗细 |
| FillRule | FillRule | EvenOdd | 填充规则(EvenOdd/Nonzero) |
| Stretch | Stretch | None | 填充模式 |
边框样式属性
| 属性 | 说明 |
|---|---|
| StrokeDashArray | 虚线模式(如 "2,1" 表示2单位实线+1单位空白) |
| StrokeDashCap | 虚线端点样式(Flat, Round, Square, Triangle) |
| StrokeLineJoin | 线段连接处样式(Miter, Bevel, Round) |
| StrokeMiterLimit | 斜接长度限制 |
使用
<Polyline
Points="10,100 100,10 200,100 300,10 400,100"
Stroke="Black" StrokeThickness="2" />

6.Polygon 多边形
Polygon(多边形)是 WPF 中用于绘制封闭多边形的形状控件
基本属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Points | PointCollection | null | 定义多边形顶点的集合 |
| Fill | Brush | null | 多边形填充画刷 |
| Stroke | Brush | null | 多边形边框画刷 |
| StrokeThickness | double | 1 | 边框粗细 |
| FillRule | FillRule | EvenOdd | 填充规则(EvenOdd/Nonzero) |
| Stretch | Stretch | None | 填充模式 |
边框样式属性
| 属性 | 说明 |
|---|---|
| StrokeDashArray | 虚线模式(如 "2,1" 表示2单位实线+1单位空白) |
| StrokeDashCap | 虚线端点样式(Flat, Round, Square, Triangle) |
| StrokeLineJoin | 线段连接处样式(Miter, Bevel, Round) |
| StrokeMiterLimit | 斜接长度限制 |
使用
<Polygon
Points="10,100 50,50 100,100 50,150"
Fill="LightBlue"
Stroke="Black"
StrokeThickness="2" />
FillRule
EvenOdd 规则(默认),从点向任意方向发射射线,计算与多边形边相交的次数:奇数次:在内部,偶数次:在外部。
<Polygon Points="20,20 80,20 80,80 20,80 40,40 60,40 60,60 40,60"
Fill="LightBlue" FillRule="EvenOdd"/>

Nonzero 规则,计算环绕数:非零:在内部,零:在外部
<Polygon Points="20,20 80,20 80,80 20,80 40,40 60,40 60,60 40,60"
Fill="LightGreen" FillRule="Nonzero"/>

对比Polyline
| 特性 | Polyline | Polygon |
|---|---|---|
| 闭合 | 不自动闭合 | 自动闭合 |
| 填充 | 必须手动闭合才能填充 | 总是可以填充 |
| 用途 | 折线图、开放路径 | 封闭形状、多边形 |
7.Path 路径
Path(路径)是 WPF 中最强大和灵活的图形控件,继承自 Shape 类,能够绘制任意复杂的矢量图形。
7.1 Path 核心属性
基本属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| Data | Geometry | null | 定义路径形状的几何图形 |
| Fill | Brush | null | 路径封闭区域的填充画刷 |
| Stroke | Brush | null | 路径描边画刷 |
| StrokeThickness | double | 1 | 描边粗细 |
| FillRule | FillRule | EvenOdd | 填充规则(EvenOdd/Nonzero) |
| Stretch | Stretch | None | 填充模式 |
边框样式属性
| 属性 | 说明 |
|---|---|
| StrokeDashArray | 虚线模式(如 "2,1" 表示2单位实线+1单位空白) |
| StrokeDashCap | 虚线端点样式(Flat, Round, Square, Triangle) |
| StrokeLineJoin | 线段连接处样式(Miter, Bevel, Round) |
| StrokeMiterLimit | 斜接长度限制 |
7.2 Path 几何数据(Data属性)
路径标记语法
<Path Data="M 起始点X,起始点Y 指令1 参数... 指令2 参数... Z"/>
常用指令:
- M - Move to (移动到)
- L - Line to (直线到)
- H - 水平线
- V - 垂直线
- C - 三次贝塞尔曲线
- Q - 二次贝塞尔曲线
- A - 椭圆弧
- Z - 闭合路径
几何对象类型
PathGeometry (路径几何)
<Path Fill="LightBlue">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="10,50">
<LineSegment Point="50,50"/>
<ArcSegment Point="100,50" Size="50,50" SweepDirection="Clockwise"/>
<BezierSegment Point1="100,100" Point2="50,100" Point3="10,50"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>
StreamGeometry (轻量路径几何)
<Path Fill="Red" Data="F1 M 10,10 L 100,10 100,100 10,80 Z"/>
GeometryGroup (几何组合)
<Path Fill="Gold">
<Path.Data>
<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"/>
<RectangleGeometry Rect="20,20 60,60"/>
</GeometryGroup>
</Path.Data>
</Path>
