WPF 入门教程(二)

2026-05-16 00:58 216 阅读

四.内容控件

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
文本格式 纯文本 富文本
性能 较低
内存占用 较多
功能 基础编辑 高级排版
使用场景 简单输入 复杂文档

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>

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>();
}

Menu(菜单)是WPF中用于构建应用程序导航系统的重要控件,主要作用包括:

1.​​提供命令访问入口​​:集中展示应用程序功能命令 2.​​组织功能分类​​:通过层级结构合理组织功能模块 3.​​节省界面空间​​:通过下拉/弹出方式隐藏非活动命令 4.​​标准化交互​​:遵循操作系统菜单交互规范 5.​​支持快捷键​​:提供键盘快捷操作方式

典型应用场景:

  • 应用程序主菜单(顶部水平菜单)
  • 上下文菜单(右键弹出菜单)
  • 工具栏下拉菜单
  • 导航菜单系统

逻辑结构:

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>