# 四.内容控件
## 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 简单使用
```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"
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 基本用法
```xml
<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>
```
```c#
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 高级用法 *
带有圆角、状态改变、图标的按钮
```xml
<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 基础用法
简单消息提示
```c#
MessageBox.Show("操作已完成!");
```
带标题的消息框
```c#
MessageBox.Show("文件保存成功", "系统提示");
```
带按钮的消息框
```c#
MessageBox.Show("确定要删除吗?", "确认删除", MessageBoxButton.YesNo);
```
#### 3.6.2 MessageBoxButton 枚举
|值 |显示的按钮|
|-|-|
|OK |确定|
|OKCancel| 确定/取消|
|YesNo| 是/否|
|YesNoCancel| 是/否/取消|
#### 3.6.3 MessageBoxImage 枚举
```c#
MessageBox.Show("磁盘空间不足", "警告",
MessageBoxButton.OK,
MessageBoxImage.Warning);
```
常用图标类型:
- None - 无图标
- Error - 错误(红色X)
- Question - 问号
- Warning - 感叹号
- Information - 信息(i图标)
#### 3.6.4 MessageBoxResult 返回值
```c#
MessageBoxResult result = MessageBox.Show("继续操作吗?",
"确认",
MessageBoxButton.YesNoCancel);
switch(result)
{
case MessageBoxResult.Yes:
// 用户点击"是"
break;
case MessageBoxResult.No:
// 用户点击"否"
break;
case MessageBoxResult.Cancel:
// 用户点击"取消"
break;
}
```
#### 3.6.5 设置默认按钮
```c#
MessageBox.Show("确认提交吗?",
"请确认",
MessageBoxButton.YesNo,
MessageBoxImage.Question,
MessageBoxResult.No); // 默认选中"否"
```
#### 3.6.6 自定义窗口所有者
```c#
// 确保消息框显示在主窗口上方
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", <Image>等|
|ContentTemplate |DataTemplate |内容模板 |自定义数据模板|
### 4.2 状态类型
- 选中(true)
- 未选中(false)
- 不确定(null)
### 4.3 简单使用
```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"
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>
```
```c#
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 基础特性与用法
基本结构
```xml
<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). 隐式分组(同父容器)**
```xml
<StackPanel>
<RadioButton Content="选项A"/>
<RadioButton Content="选项B"/> <!-- 与选项A互斥 -->
</StackPanel>
```
**2). 显式分组(GroupName)**
```xml
<RadioButton Content="红色" GroupName="Color"/>
<RadioButton Content="绿色" GroupName="Color"/> <!-- 颜色组 -->
<RadioButton Content="大号" GroupName="Size"/>
<RadioButton Content="小号" GroupName="Size"/> <!-- 尺寸组 -->
```
**3).复杂分组示例**
```xml
<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 基础用法
```xml
<RepeatButton Content="+" Width="30" Height="30" Click="Increase_Click"/>
```
```c#
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) |重复触发的时间间隔|
<RepeatButton Content="加速+"
Delay="200"
Interval="50"
Click="Accelerate_Click"/>
### 6.4 事件处理
|事件 |描述|
|-|-|
|Click |每次触发时发生|
|PreviewMouseDown |鼠标按下时(首次触发前)|
|PreviewMouseUp |鼠标释放时|
# 7.Label标签
Label 是 WPF 中用于显示文本内容的轻量级控件,相比 TextBlock 提供了更多与表单输入控件协作的功能。。
## 7.1 基础特性与用法
基本结构
```xml
<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)
```xml
<Label Content="_Username:" Target="{Binding ElementName=txtUser}"/>
<TextBox x:Name="txtUser"/>
<!-- 按Alt+U将聚焦到文本框 -->
```
#### 7.2.2 多目标关联
```xml
<StackPanel>
<Label x:Name="lblGroup" Content="个人资料"/>
<CheckBox Content="姓名" Target="{Binding ElementName=lblGroup}"/>
<CheckBox Content="年龄" Target="{Binding ElementName=lblGroup}"/>
</StackPanel>
```
### 7.3 内容呈现
```xml
<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 基础文本显示
文本设置方式
```xml
<!-- 直接文本 -->
<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 高级文本格式化
内联元素类型
```xml
<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|
高级渲染控制
```xml
<!-- 抗锯齿优化 -->
<TextBlock TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"/>
<!-- 文本阴影 -->
<TextBlock Text="特效文本">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="4" ShadowDepth="3" Color="#88000000"/>
</TextBlock.Effect>
</TextBlock>
```
### 8.4 渲染性能优化
```xml
<!-- 启用硬件渲染 -->
<TextBlock CacheMode="BitmapCache"/>
<!-- 大量文本优化 -->
<TextBlock Text="{Binding LogContent}"
TextOptions.TextFormattingMode="Display"
IsTextSelectionEnabled="False"/>
```
### 8.5 超链接
```xml
<TextBlock>
<Hyperlink NavigateUri="https://www.baidu.com" RequestNavigate="Hyperlink_RequestNavigate">
点击访问
</Hyperlink>
</TextBlock>
```
```c#
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 基本用法
```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"
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 水印
```xml
<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 简单用法
```xml
<PasswordBox Password="123456" PasswordChar="*"/>
```

### 10.2 常用属性
密码相关
•Password: 获取或设置密码框中包含的密码(不直接绑定)
•PasswordChar: 获取或设置用于屏蔽密码的字符(默认是圆点●)
外观相关
- Background: 背景色
- Foreground: 前景色(文本颜色)
- BorderBrush: 边框颜色
- BorderThickness: 边框粗细
- FontFamily: 字体
- FontSize: 字体大小
- FontWeight: 字体粗细
- SelectionBrush: 文本选中时的背景色
- SelectionOpacity: 文本选中时背景色的透明度
- CaretBrush: 光标颜色
行为相关
- MaxLength: 最大输入字符数
- IsEnabled: 是否启用
- PasswordChanged: 密码更改时触发的事件
### 10.3 密码安全处理
安全获取密码
```c#
// 不安全方式(字符串会留在内存中)
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|
|-|-|-|
|文本格式 |纯文本| 富文本|
|性能 |高 |较低|
|内存占用| 少| 较多|
|功能| 基础编辑 |高级排版|
|使用场景 |简单输入 |复杂文档|
[RichTextBox介绍](https://learn.microsoft.com/zh-cn/dotnet/desktop/wpf/controls/richtextbox?view=netframeworkdesktop-4.8)
## 12.Tooltip 提示
ToolTip 是 WPF 中用于显示额外信息的弹出式控件,当用户将鼠标悬停在元素上时显示提示内容。
### 12.1 核心特点
- 轻量级信息展示:不干扰主界面布局
- 悬停触发:默认鼠标悬停时显示
- 富内容支持:可包含任意可视化元素
- 高度可定制:完全控制外观和行为
- 自动定位:智能避开屏幕边缘
### 12.2 基本使用
简单文本提示
```xml
<Button Content="提交" ToolTip="点击提交表单数据"/>
```
通过属性设置
```xml
<Button Content="保存">
<Button.ToolTip>
<ToolTip Content="保存当前文档"/>
</Button.ToolTip>
</Button>
```
多行文本提示
```xml
<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 交互控制
编程控制显示
```c#
// 创建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事件
```xml
<Button Content="事件测试">
<Button.ToolTip>
<ToolTip x:Name="testToolTip"
Opened="ToolTip_Opened"
Closed="ToolTip_Closed"
Content="事件演示ToolTip"/>
</Button.ToolTip>
</Button>
```
```c#
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
```xml
<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声明
```xml
<Popup x:Name="simplePopup" Placement="Mouse">
<Border Background="White" BorderBrush="Gray" BorderThickness="1">
<TextBlock Margin="10" Text="这是一个简单的Popup"/>
</Border>
</Popup>
```
2.通过代码控制显示
```c#
// 显示Popup
simplePopup.IsOpen = true;
// 关闭Popup
simplePopup.IsOpen = false;
```
3.绑定触发按钮
```xml
<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事件
```xml
<Popup x:Name="eventPopup" Opened="Popup_Opened" Closed="Popup_Closed">
<!-- 内容 -->
</Popup>
```
保持焦点控制
```xml
<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 基本使用方式
从文件加载
```xml
<Image Source="C:\Users\luyuanwen\Desktop\图片\111.gif"/>
```
从项目资源加载
```xml
<!-- 添加图像到项目Resources文件夹 -->
<Image Source="Resources/icon.png"/>
```
从URI加载
```xml
<Image Source="https://www.diandiandidi.club/favicon.ico"/>
```
代码加载
```c#
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 高级用法
图像裁剪
```xml
<Image Source="photo.jpg">
<Image.Clip>
<EllipseGeometry Center="100,100" RadiusX="80" RadiusY="80"/>
</Image.Clip>
</Image>
```
图像变换
```xml
<Image Source="photo.jpg">
<Image.RenderTransform>
<TransformGroup>
<RotateTransform Angle="15"/>
<ScaleTransform ScaleX="0.8" ScaleY="0.8"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
```
图像蒙版
```xml
<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 性能优化
解码像素大小
```c#
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri("large_image.jpg");
bitmap.DecodePixelWidth = 800; // 限制解码宽度
bitmap.DecodePixelHeight = 600; // 限制解码高度
bitmap.EndInit();
imageControl.Source = bitmap;
```
缓存选项
```c#
bitmap.CacheOption = BitmapCacheOption.OnLoad; // 立即加载并缓存,可以防止锁定图像
```
## 15.GroupBox分组
GroupBox 是 WPF 中用于将相关控件分组并提供视觉分隔的容器控件,继承自 System.Windows.Controls.HeaderedContentControl
### 15.1 基本概念与特性
核心特点
- 分组容器:将相关控件组织在一起
- 标题显示:带有可自定义的标题区域
- 视觉分隔:提供边框和背景区分不同组
- 布局控制:作为内容控件,可包含任意子元素
- 键盘导航:支持通过标题快速导航到内容。按下Tab键后,优先导航到GroupBox,之后方向键选择可以聚焦的内容。
与类似控件对比
|特性 |GroupBox |Expander |TabControl| Border|
|-|-|-|-|-|
|标题 |有 |有 |有(标签页)| 无|
|折叠功能 |无 |有 |无 |无|
|边框 |有 |有 |有 |有|
|内容切换| 无 |展开/折叠 |标签页切换 |无|
### 15.2 基本使用
简单 GroupBox
```xml
<GroupBox Header="用户信息">
<StackPanel>
<TextBox Margin="5" Text="姓名"/>
<TextBox Margin="5" Text="年龄"/>
</StackPanel>
</GroupBox>
```
带复杂标题
```xml
<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
典型用途:显示大型内容、长列表、图片查看器等
基本用法:
```xml
<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|
常用方法
```c#
// 滚动控制
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 基本使用
```xml
<!-- 水平滑块 -->
<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 基本使用
基本声明
```xml
<!-- 确定进度模式 -->
<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 圆角进度条
```xml
<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日历
提供日期选择功能的可视化日历控件
基本使用
```xml
<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集合|
常用方法
```c#
// 添加不可选日期
calendar.BlackoutDates.Add(new CalendarDateRange(startDate, endDate));
// 清除所有选择
calendar.SelectedDates.Clear();
// 导航到特定月份
calendar.DisplayDate = new DateTime(2023, 7, 1);
```
事件处理
|事件 |触发时机|
|-|-|
|SelectedDatesChanged |选中日期变化时|
|DisplayDateChanged |显示月份变化时|
```c#
calendar.SelectedDatesChanged += (sender, e) => {
var selectedDates = ((Calendar)sender).SelectedDates;
// 处理选中日期
};
```
## 21.DatePicker日期选择
提供日期选择功能的输入控件
使用
```xml
<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 |空|
常用方法
```c#
// 清空选择
datePicker.SelectedDate = null;
// 添加不可选日期
datePicker.BlackoutDates.Add(new CalendarDateRange(startDate, endDate));
// 获取格式化文本
string dateString = datePicker.Text;
```
事件处理
|事件| 触发时机|
|-|-|
|SelectedDateChanged| 选中日期变化时|
|DateValidationError| 日期验证失败时|
|CalendarOpened| 日历展开时|
|CalendarClosed |日历关闭时|
## 22.MediaElement媒体播放
```xml
<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| 当前播放位置|
播放控制实现
```c#
// 播放
mediaPlayer.Play();
// 暂停
mediaPlayer.Pause();
// 停止
mediaPlayer.Stop();
// 定位
mediaPlayer.Position = TimeSpan.FromSeconds(30);
```
## 23.Expander 折叠控件
可展开/折叠的内容容器,带有标题和切换按钮
```xml
<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 虚拟化
对于大量数据,可以使用虚拟化提高性能
```xml
<ListBox VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"/>
```
### 1.4 使用
#### 14.1 简单使用
从下面选项中选择一项或者多项
```xml
<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>
```
```c#
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 代码添加数据
```xml
<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>
```
```c#
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 使用对象作为数据项
```xml
<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>
```
```c#
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 处理数据源变更
数据源变更包括删除、增加项以及修改项。
错误变更数据源案例:
```c#
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集合,该集合数据变更时会进行通知更新。
```c#
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);
}
}
```
变更数据源某项属性案例:
```xml
<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>
```
```c#
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 自定义模板
```xml
<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,但提供了更丰富的显示功能,特别是支持多列视图(类似表格)。
```xml
<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>
```
```c#
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 基本使用
基本语法:
```xml
<DataGrid x:Name="dataGrid">
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Id}"/>
<DataGridTextColumn Header="姓名" Binding="{Binding Name}"/>
</DataGrid.Columns>
</DataGrid>
```
数据绑定方式:
自动生成列
```xml
<DataGrid AutoGenerateColumns="True"/>
```
手动定义列
```xml
<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 核心功能
排序功能:
```xml
<DataGrid CanUserSortColumns="True">
<DataGrid.Columns>
<DataGridTextColumn Header="日期"
Binding="{Binding Date}"
SortDirection="Descending"/>
</DataGrid.Columns>
</DataGrid>
```
编辑功能:
```xml
<DataGrid CanUserAddRows="True" <!-- 允许添加行 -->
CanUserDeleteRows="True" <!-- 允许删除行 -->
CanUserEditRows="True"> <!-- 允许编辑行 -->
</DataGrid>
```
选择模式:
```xml
<DataGrid SelectionMode="Extended" <!-- 多选模式 -->
SelectionUnit="FullRow"> <!-- 整行选择 -->
</DataGrid>
```
行详细信息:
```xml
<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 高级功能
自定义列模板
```xml
<DataGridTemplateColumn Header="操作">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Content="编辑" Command="{Binding EditCommand}"/>
<Button Content="删除" Command="{Binding DeleteCommand}"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
```
分组显示
```xml
<DataGrid>
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
```
### 3.5 DataGrid 样式与模板
行样式
```xml
<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>
```
交替行颜色
```xml
<DataGrid AlternationCount="2"
AlternatingRowBackground="LightGray"/>
```
单元格样式
```xml
<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 性能优化
虚拟化技术
```xml
<DataGrid EnableRowVirtualization="True"
EnableColumnVirtualization="True"
VirtualizingPanel.VirtualizationMode="Recycling"/>
```
冻结列
```xml
<DataGrid FrozenColumnCount="2"> <!-- 冻结前两列 -->
</DataGrid>
```
延迟滚动
```xml
<DataGrid ScrollViewer.IsDeferredScrollingEnabled="True"/>
```
### 3.7 常见问题
#### 3.7.1 自动生成列自定义
```c#
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 大数据量处理
```xml
<DataGrid VirtualizingPanel.ScrollUnit="Pixel"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
ScrollViewer.IsDeferredScrollingEnabled="True"/>
```
#### 3.7.3 行双击事件
```xml
<DataGrid MouseDoubleClick="DataGrid_MouseDoubleClick"/>
```
#### 3.7.4 可编辑数据表格
```xml
<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>
```
```c#
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:
样式在后期,这里先使用
```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#
```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 基本用法
静态项定义
```xml
<ComboBox>
<ComboBoxItem>选项1</ComboBoxItem>
<ComboBoxItem>选项2</ComboBoxItem>
<ComboBoxItem>选项3</ComboBoxItem>
</ComboBox>
```
数据绑定方式
```xml
<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 案例-搜索下拉
```xml
<ComboBox x:Name="comboBox" SelectedValuePath="Name"
DisplayMemberPath="Name" DropDownOpened="ComboBox_DropDownOpened"
PreviewKeyUp="ComboBox_PreviewKeyUp"
IsEditable="True" IsTextSearchEnabled="False" Width="200" Height="30"/>
```

```c#
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 基本用法
```xml
<TabControl>
<TabItem Header="首页">
<TextBlock Text="欢迎来到首页"/>
</TabItem>
<TabItem Header="设置">
<StackPanel>
<CheckBox Content="启用通知"/>
<Slider Maximum="100"/>
</StackPanel>
</TabItem>
</TabControl>
```

数据绑定方式
```xml
<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 动态添加/移除选项卡
```c#
// 添加选项卡
var newTab = new TabItem { Header = "新标签", Content = new UserControl1() };
tabControl.Items.Add(newTab);
// 移除当前选项卡
tabControl.Items.Remove(tabControl.SelectedItem);
```
### 5.5 选项卡位置控制
```xml
<TabControl TabStripPlacement="Left">
<!-- 选项卡将显示在左侧 -->
</TabControl>
```
可选值:Top(默认)、Bottom、Left、Right
### 5.6 案例-左侧导航
```xml
<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 基本用法
```xml
<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文档大纲查看
```xml
<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>
```
```c#
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 控件的结构
逻辑结构:
```language
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 作为顶部菜单使用
```xml
<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 基类中的。因此大多数控件均可以右键更多操作。
```xml
<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.用户引导:显示当前可执行操作的提示信息
典型应用场景:
- 文本编辑器的行列号显示
- 图像处理软件的缩放比例和颜色信息
- 数据库应用的连接状态
- 应用程序的进度指示
```xml
<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 使用
```xml
<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 |填充模式|
使用:
简单使用
```xml
<Ellipse Width="100" Height="100"
Fill="Blue" Stroke="Black"
StrokeThickness="2"/>
```

画刷
```xml
<Ellipse Width="120" Height="120">
<Ellipse.Fill>
<RadialGradientBrush>
<GradientStop Color="Yellow" Offset="0"/>
<GradientStop Color="Red" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
```

变换:
```xml
<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 |虚线偏移量|
使用:
```xml
<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 |斜接长度限制|
使用:
```xml
<Rectangle Canvas.Top="10" Canvas.Left="10"
StrokeThickness="3" RadiusX="10" RadiusY="10"
Width="200" Height="100" Fill="Red" Stroke="Blue"/>
```

```xml
<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| 斜接长度限制|
使用
```xml
<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| 斜接长度限制|
使用
```xml
<Polygon
Points="10,100 50,50 100,100 50,150"
Fill="LightBlue"
Stroke="Black"
StrokeThickness="2" />
```

**FillRule**
EvenOdd 规则(默认),从点向任意方向发射射线,计算与多边形边相交的次数:奇数次:在内部,偶数次:在外部。
```xml
<Polygon Points="20,20 80,20 80,80 20,80 40,40 60,40 60,60 40,60"
Fill="LightBlue" FillRule="EvenOdd"/>
```

Nonzero 规则,计算环绕数:非零:在内部,零:在外部
```xml
<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属性)
路径标记语法
```xml
<Path Data="M 起始点X,起始点Y 指令1 参数... 指令2 参数... Z"/>
```
常用指令:
- M - Move to (移动到)
- L - Line to (直线到)
- H - 水平线
- V - 垂直线
- C - 三次贝塞尔曲线
- Q - 二次贝塞尔曲线
- A - 椭圆弧
- Z - 闭合路径
几何对象类型
PathGeometry (路径几何)
```xml
<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 (轻量路径几何)
```xml
<Path Fill="Red" Data="F1 M 10,10 L 100,10 100,100 10,80 Z"/>
```

GeometryGroup (几何组合)
```xml
<Path Fill="Gold">
<Path.Data>
<GeometryGroup>
<EllipseGeometry Center="50,50" RadiusX="40" RadiusY="40"/>
<RectangleGeometry Rect="20,20 60,60"/>
</GeometryGroup>
</Path.Data>
</Path>
```
