- UI组件
- 桌面应用
【免费下载链接】HandyControl
Contains some simple and commonly used WPF controls
本文基于 HandyControl 开源仓库中 RadioButton 原生控件文档 展开,系统讲解 WPF 单选按钮的RadioButtonBaseStyle默认样式与RadioButtonIcon图标样式,并结合仓库源码剖析其动画模板、交互触发器与附加属性的底层实现,帮助开发者在实际项目中正确选用、复用和定制单选按钮样式。
样式体系概览
HandyControl 将 RadioButton 的样式拆分为"基样式层"与"派生样式层"两层结构:
- 基样式层:定义在 Base/RadioButtonBaseStyle.xaml 中,包含
RadioButtonBaseStyle、RadioButtonSameAsButtonBaseStyle、RadioButtonIconBaseStyle、RadioGroupItemBaseStyle四个基础样式,属于底层可复用样式; - 派生样式层:定义在 Styles/RadioButton.xaml 中,通过
BasedOn继承基样式并追加默认资源,对外暴露可直接使用的具名样式。
文档明确强调一条设计原则:单选按钮默认样式不推荐直接使用,应该始终被其它样式以 BasedOn 的方式使用。也就是说,RadioButtonBaseStyle扮演的是"样式基座"角色,其模板细节由 RadioButton.xaml 第 5 行通过BasedOn="{StaticResource RadioButtonBaseStyle}"隐式应用到所有未指定样式的 RadioButton 上,同时也可作为自定义样式的 BasedOn 源。
RadioButtonBaseStyle:默认单选按钮样式
基础用法
文档给出的最小使用案例覆盖了单选按钮最常见的三种状态:默认、选中(IsChecked="True")、不可编辑(IsEnabled="False"):
<StackPanel> <RadioButton Content="默认样式"/> <RadioButton Margin="0,16,0,0" Content="不可编辑" IsChecked="True" IsEnabled="False"/> <RadioButton Margin="0,16,0,0" Content="默认样式"/> <RadioButton Margin="0,16,0,0" Content="不可编辑" IsEnabled="False"/> </StackPanel>由于 RadioButton.xaml 中定义了基于RadioButtonBaseStyle的隐式样式(TargetType="RadioButton"),上述 XAML 无需显式指定Style即可直接应用默认外观。
源码级解析:模板结构与动画
从 Base/RadioButtonBaseStyle.xaml 的实现看,默认样式的核心视觉是一个16×16、圆角为 8 的圆形选项框:
- 外层
Border填充Background(RegionBrush),内部嵌套 8×8 的白色Ellipse(optionMark)作为选中圆点; - 选中圆点默认通过
RenderTransform中的ScaleTransform缩放到 0(不可见),选中时由两个Storyboard(StoryboardCheckedTrue/StoryboardCheckedFalse)驱动ScaleX、ScaleY在 0 与 1 之间以 0.1 秒的EasingDoubleKeyFrame动画过渡,形成圆点"弹入/弹出"的平滑效果; - 第二列
ContentPresenter的Visibility初始为Collapsed,当HasContent=true时通过触发器显示内容,Margin绑定Padding(默认6,0,0,0),保证文字与选项框间距。
交互状态由模板触发器(ControlTemplate.Triggers)统一管理:
| 状态 | 触发条件 | 视觉表现 |
|---|---|---|
| 悬停 | IsMouseOver=true | 边框切换为SecondaryBorderBrush |
| 按下-选中 | IsChecked=true且IsPressed=true | 整体Opacity=.8 |
| 按下-未选中 | IsChecked=false且IsPressed=true | 边框切换为PrimaryBrush |
| 选中 | IsChecked=true | 背景切换为PrimaryBrush、边框切换为DarkPrimaryBrush,隐藏外层边框以突出选中圆点 |
| 禁用 | IsEnabled=false | 整体Opacity=0.4 |
值得留意的是FocusVisualStyle:选中/聚焦时绘制一圈StrokeDashArray="1 1"的虚线圆角矩形,便于键盘导航场景下明确焦点位置。
RadioButtonIcon:带图标样式
RadioButtonIcon是基于RadioButtonIconBaseStyle的派生样式(定义见 Styles/RadioButton.xaml 第 81 行),特点是可只显示图标,也可图文同时显示。它不再使用传统圆点选项框,而是"矩形块 + 图标"的形态,通常用于工具栏、标签页或分组选择场景。
基础用法
文档给出的案例在一个 2×2 的UniformGrid中演示了四种组合:图标+文字、仅文字(选中态)、带边框的图标+文字、带边框的仅文字:
<UniformGrid Margin="22,0,0,0" Rows="2" Columns="2"> <RadioButton Margin="10,0,0,0" Background="{DynamicResource SecondaryRegionBrush}" hc:IconElement.Geometry="{StaticResource CalendarGeometry}" Style="{StaticResource RadioButtonIcon}" Content="RadioButtonIcon"/> <RadioButton Margin="10,0,0,0" Background="{DynamicResource SecondaryRegionBrush}" Style="{StaticResource RadioButtonIcon}" Content="RadioButtonIcon" IsChecked="True"/> <RadioButton Margin="10,0,0,0" BorderThickness="1" hc:IconElement.Geometry="{StaticResource CalendarGeometry}" Style="{StaticResource RadioButtonIcon}" Content="RadioButtonIcon"/> <RadioButton Margin="10,0,0,0" BorderThickness="1" Style="{StaticResource RadioButtonIcon}" Content="RadioButtonIcon"/> </UniformGrid>图标与内容的自动显隐
RadioButtonIconBaseStyle的模板由hc:SimplePanel承载两块内容:
- 一个
Border(背景、边框均可通过TemplateBinding绑定),内部为横向StackPanel:Path(图标)与ContentPresenter(文字); - 一个左侧高亮条
BorderHighlight(BorderThickness="3,0,0,0"),选中时切换为VisualElement.HighlightBrush,用于在选中项左侧显示竖线标记。
模板触发器实现了两个重要的自动显隐逻辑:
Content为{x:Null}时隐藏ContentPresenterMain,实现只显示图标;hc:IconElement.Geometry为{x:Null}时隐藏PathMain并清除文字左间距,实现只显示文字。
图标数据通过hc:IconElement.Geometry附加属性注入。该附加属性定义在 Controls/Attach/IconElement.cs 中,除Geometry外还提供Width、Height两个附加属性(默认值为NaN,即保持图标原始尺寸)。示例中使用的CalendarGeometry是仓库内置的几何资源,定义于 Themes/Basic/Geometries.xaml,也可替换为任意Geometry数据或自定义图标。
RadioButtonIcon系列还有小尺寸变体RadioButtonIcon.Small(高度 20、Padding6,1、图标高度 12),适用于紧凑布局。
同按钮系列样式:RadioButtonSameAsButton*
RadioButtonBaseStyle.xaml中的RadioButtonSameAsButtonBaseStyle让单选按钮呈现按钮的外观——选中后通过 4px 的DarkMaskBrush内边框(BorderChecked)标记,同样支持图标+文字或仅图标两种形态。基于它派生的 Styles/RadioButton.xaml 提供了完整的语义色与尺寸矩阵:
| 样式 Key | 语义色 |
|---|---|
RadioButtonSameAsButtonDefault/.Small | RegionBrush+PrimaryTextBrush |
RadioButtonSameAsButtonPrimary/.Small | PrimaryBrush |
RadioButtonSameAsButtonSuccess/.Small | SuccessBrush |
RadioButtonSameAsButtonInfo/.Small | InfoBrush |
RadioButtonSameAsButtonWarning/.Small | WarningBrush |
RadioButtonSameAsButtonDanger/.Small | DangerBrush |
.Small变体统一将高度设为 20、Padding 设为6,1、图标高度设为 12。这些颜色资源均来自主题系统,切换皮肤(Default/Dark/Violet)时自动跟随变化。
按钮组系列样式:RadioGroupItem*
RadioGroupItemBaseStyle(定义于 Base/RadioButtonBaseStyle.xaml)专为与hc:ButtonGroup容器配合设计,选中项通过hc:VisualElement.HighlightBackground/HighlightBorderBrush/HighlightForeground三组附加属性改变整体配色,并利用Panel.ZIndex=int.MaxValue保证选中项浮于相邻项之上。其派生样式按容器方向与位置细分:
RadioGroupItemDefault:默认圆角为 0;RadioGroupItemHorizontalFirst:圆角4,0,0,4(水平分组左侧首项);RadioGroupItemHorizontalLast:圆角0,4,4,0(水平分组右侧末项);RadioGroupItemVerticalFirst:圆角4,4,0,0(垂直分组顶部首项);RadioGroupItemVerticalLast:圆角0,0,4,4(垂直分组底部末项);RadioGroupItemSingle:使用DefaultCornerRadius的独立圆角项。
VisualElement.Highlight*附加属性在 Controls/Attach/VisualElement.cs 中定义,均以DynamicResource主题刷子为默认值,可在元素上直接覆盖指定。
从 Demo 中获取完整参考
仓库自带的演示页面 UserControl/Styles/RadioButtonDemo.xaml 集中展示了上述全部样式的实际用法:
- 六个语义色(Default/Primary/Success/Info/Warning/Danger)的
RadioButtonSameAsButton*及.Small变体,每种都包含正常与禁用两种状态; - 同一组变体配合
hc:IconElement.Geometry的图标+文字用法,以及不设Content的纯图标用法(如RotateLeftGeometry、RotateRightGeometry、LeftGeometry、RightGeometry); - 默认
RadioButtonBaseStyle与RadioButtonIcon/RadioButtonIcon.Small的纵向演示,与文档案例一一对应。
跨平台版本说明
除 WPF 版本外,仓库还维护了 Avalonia 实现 Themes/Styles/RadioButton.axaml,其中RadioButtonBaseStyle、RadioButtonIcon、RadioButtonSameAsButton*、RadioGroupItem*等样式 Key 与 WPF 版本保持一致(Avalonia 中使用ControlTheme而非Style),动画通过TransformOperationsTransition实现选中圆点的缩放过渡。若项目基于 Avalonia 而非 WPF,可直接参考该文件中的同名样式定义。
使用建议
- 若需要自定义单选按钮外观,请以
RadioButtonBaseStyle为BasedOn源编写新样式,而不是在页面中逐个修改默认样式; - 需要"图标+文字"或"纯图标"的按钮化单选时,优先使用
RadioButtonIcon(及.Small),并配合hc:IconElement.Geometry注入图标; - 需要与
hc:ButtonGroup组合成横向/纵向分段选择器时,按首、中、末位置选用RadioGroupItemHorizontalFirst、RadioGroupItemDefault、RadioGroupItemHorizontalLast等系列样式; - 关注状态覆盖:所有样式对
IsEnabled="False"统一采用Opacity=0.4表达禁用态,悬停、按下、选中态均有明确的视觉反馈,无需额外编写状态逻辑。
- UI组件
- 桌面应用
【免费下载链接】HandyControl
Contains some simple and commonly used WPF controls
相关推荐
Ant Design 按钮样式单选框:RadioButton 与 RadioGroup 组合实战指南
Ant Design 按钮样式单选框:RadioButton 与 RadioGroup 组合实战指南 Ant Design 在标准圆形单选控件之外,提供了按钮样
UI组件前端设计系统如何用 Element UI 的 Radio 和 RadioButton 实现按钮样式的单选选项组?
如何用 Element UI 的 Radio 和 RadioButton 实现按钮样式的单选选项组? 如果你在一个 Vue 2 项目里用 Element UI(
前端UI组件设计系统CANN ops-nn 算子开发实战:aclnnSoftsignBackward 接口原理与两段式调用全解
CANN ops nn 算子开发实战:aclnnSoftsignBackward 接口原理与两段式调用全解 导读 本文以 CANN ops nn 仓库中 exp
UI组件桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考