一、功能概述
- BulletDecorator 是轻量级布局原语,用于在一行内排布"子弹元素"(Bullet)与"内容元素"(Child)。
- 常见于 CheckBox/RadioButton 的控件模板:左侧图标(勾/点),右侧文本。
- 要点
- Bullet/Child 均为任意 UIElement(Ellipse/Path/Button/TextBlock/ContentPresenter 等)。
- 先测量 Bullet 的 DesiredSize,再将剩余宽度提供给 Child;受 FlowDirection 影响(RTL 时子弹在右)。
- 间距用元素 Margin 控制;命中区域可通过设置 Background 扩大(例如 Transparent)。
二、使用方式(Active Document)
- XAML:多个典型子弹形态(圆点、Path 图标、交互按钮、RTL)
xml
<UserControl x:Class="H.Test.DataGrid.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Margin="12" Orientation="Vertical" >
<!-- 圆点 + 文本 -->
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Ellipse Width="14" Height="14" Fill="#4090F0" Stroke="#2E6CB8"/>
</BulletDecorator.Bullet>
<TextBlock Text="这是 BulletDecorator 的内容"
Margin="8,0,0,0"
VerticalAlignment="Center"/>
</BulletDecorator>
<!-- Path 作为子弹图标 -->
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Path Width="16" Height="16" Stretch="Uniform"
Fill="#FF2CA6"
Data="M12,2 L2,12 L6,12 L6,18 L10,18 L10,12 L14,12 Z"/>
</BulletDecorator.Bullet>
<TextBlock Text="使用 Path 作为子弹图标"
Margin="8,0,0,0"
VerticalAlignment="Center"/>
</BulletDecorator>
<!-- 交互型子弹(按钮) -->
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Button Width="18" Height="18" Padding="0" Content="i"/>
</BulletDecorator.Bullet>
<TextBlock Text="可交互的子弹元素(例如提示按钮)"
Margin="8,0,0,0"
VerticalAlignment="Center"/>
</BulletDecorator>
<!-- RTL 布局:子弹在右侧 -->
<Border FlowDirection="RightToLeft">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Ellipse Width="12" Height="12" Fill="Orange"/>
</BulletDecorator.Bullet>
<TextBlock Text="RTL 布局示例(子弹在右侧)"
Margin="8,0,0,0"
VerticalAlignment="Center"/>
</BulletDecorator>
</Border>
</StackPanel>
</UserControl>
三、与 HeaderedContentControl 的区别
- 定位与职责
- BulletDecorator:布局原语,只负责"子弹 + 内容"的并排布局;不提供数据模板或标题语义。
- HeaderedContentControl:控件基类(如 GroupBox/Expander),提供 Header 与 Content 两区域,可用 HeaderTemplate/ContentTemplate/TemplateSelector。
- 内容模型
- BulletDecorator:两个元素位(Bullet/Child),你提供具体 UIElement。
- HeaderedContentControl:Header/Content 可绑定任意数据并通过模板呈现,语义更强。
- 样式与主题化
- BulletDecorator:常用于控件模板内部,定制点少。
- HeaderedContentControl:完整控件样式/模板体系,适合主题化和复用。
- 可访问性
- BulletDecorator:无内置标题语义。
- HeaderedContentControl:Header 参与 UI 自动化,更利于无障碍与测试。
- 选择建议
- 简单"图标+文本"横排:用 BulletDecorator。
- 需要"标题+内容"且可模板化:用 HeaderedContentControl。
四、与 Panel 布局的区别
- 职责边界
- BulletDecorator:专用于两段式"Bullet + Child"的水平布局(受 FlowDirection 影响),非通用面板。
- Panel(StackPanel/Grid/DockPanel/WrapPanel/Canvas):通用容器,负责任意数量子元素的排列与定位。
- 行为对比
- StackPanel:按方向顺序堆叠多个子元素;不能直接表达"固定 Bullet + 自适应内容"的二元关系。
- Grid:网格单元格布局,需显式列/行定义;实现"子弹 + 内容"通常需要两列。
- DockPanel:四边停靠;实现"子弹 + 内容"需靠 Dock 与 LastChildFill。
- WrapPanel:自动换行;不适合"一粒子弹 + 一段内容"的严格并排。
- Canvas:绝对定位;需要手动坐标,通常不适合数据驱动 UI。
- 性能与简单性
- BulletDecorator:单一目的,视觉树更浅,模板内使用简洁。
- Panel:灵活通用,但为此场景通常更"重"。
五、文档链接
- BulletDecorator | Microsoft Learn
- HeaderedContentControl | Microsoft Learn
- StackPanel | Microsoft Learn
- Grid | Microsoft Learn
- DockPanel | Microsoft Learn
- WrapPanel | Microsoft Learn
- Canvas | Microsoft Learn
- Panel | Microsoft Learn
提示
- 为更好点击体验,可给 BulletDecorator 设置 Background="Transparent"。
- 间距建议用 Child 的 Margin;需要右侧子弹时使用 FlowDirection="RightToLeft"。
了解更多
System.Windows.Controls 命名空间 | Microsoft Learn
控件库 - WPF .NET Framework | Microsoft Learn
使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn
HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频