☰
ant-design-blazor 枚举单选框 EnumRadioGroup 实战指南:声明一个枚举,自动渲染整个 RadioGroup
2026/10/12 1:31:11 网站建设 项目流程
  • UI组件
  • 前端

【免费下载链接】ant-design-blazor

🌈A rich set of enterprise-class UI components based on Ant Design and Blazor.

项目地址:https://gitcode.com/gh_mirrors/an/ant-design-blazor
点击查看免费下载

导读

在 ant-design-blazor 的 Radio 组件体系中,除了手写<Radio>子项和Options数组两种方式外,还提供了一条"零配置"路径:EnumRadioGroup<TEnum>。你只需要定义一个 C# 枚举类型,组件就会在构造时自动遍历枚举成员并生成对应的一组单选框,配合System.ComponentModel.DataAnnotations.Display特性还能自定义每个选项的显示文案。本文以仓库 demo enum-group.md 为骨架,结合 EnumRadioGroup.cs、EnumHelper.cs 与 RadioGroup.razor.cs 的源码,完整讲解它的用法、原理、参数与项目实战场景。

一、枚举方式的核心用法

原 demo 文档的核心表述只有一句:"通过指定枚举类型,来渲染单选框"(Render radios by specific enum type)。在 ant-design-blazor 中,这一能力由泛型组件EnumRadioGroup<TEnum>提供,完整示例见 EnumGroup.razor:

@using System.ComponentModel.DataAnnotations <EnumRadioGroup TEnum="Fruits" @bind-Value="_radioValue" Disabled="_disabled" Name="group1"></EnumRadioGroup> <br /> <EnumRadioGroup TEnum="Fruits" @bind-Value="_radioValue" Disabled="_disabled" ButtonStyle="RadioButtonStyle.Solid" Name="group2"></EnumRadioGroup> <br /> Value: @_radioValue <div style="margin-top: 20px"> <Button Type="ButtonType.Primary" OnClick="_=>_disabled=!_disabled">Toggle Disabled</Button> </div> @code { Fruits _radioValue = Fruits.Apple; bool _disabled; enum Fruits { [Display(Name = "🍎 Apple")] Apple, Pear, Orange } }

使用要点可拆解为四步:

  1. 定义枚举类型:示例中的Fruits枚举包含Apple、Pear、Orange三个成员,其中Apple通过[Display(Name = "🍎 Apple")]指定了自定义显示文本;
  2. 声明组件并指定泛型参数:TEnum="Fruits"告诉组件要渲染哪个枚举;
  3. 绑定当前选中值:@bind-Value="_radioValue"与Fruits _radioValue = Fruits.Apple;双向绑定,初始默认选中Apple;
  4. 按需传入其余参数:Disabled控制整组禁用、Name设置所有原生input[type="radio"]的 name 属性、ButtonStyle切换按钮风格。

demo 还搭配了一个Toggle Disabled按钮,通过_=>_disabled=!_disabled切换整组禁用状态,方便直观观察禁用效果。

二、为什么枚举方式能"自动渲染":源码实现原理

2.1 EnumRadioGroup :构造函数即渲染

EnumRadioGroup<TEnum>的完整实现非常精简,全部逻辑集中在构造函数中:

public class EnumRadioGroup<TEnum> : RadioGroup<TEnum> { public EnumRadioGroup() { Options = EnumHelper<TEnum>.GetValueLabelList() .Select(x => new RadioOption<TEnum> { Value = x.Value, Label = x.Label }) .ToArray(); } }

从源码结构可以梳理出它的工作流程:

  1. 组件继承自RadioGroup<TEnum>(见 EnumRadioGroup.cs),因此天然具备RadioGroup的全部能力与参数;
  2. 构造函数调用EnumHelper<TEnum>.GetValueLabelList(),一次性取出枚举的"值 + 显示名"列表;
  3. 将列表映射为RadioOption<TEnum>数组并赋给Options属性;
  4. RadioGroup的渲染模板检测到Options非空后,不再渲染ChildContent子内容,而是遍历Options逐个生成<Radio>,见 RadioGroup.razor 中Options.IsT1分支:
@foreach (var radio in Options.AsT1) { <Radio Value="radio.Value" RadioButton="IsButton">@radio.Label</Radio> }

也就是说,"渲染单选框"这件事完全由枚举到Options的自动转换完成,用户无需再手写任何<Radio>子项。

2.2 EnumHelper :枚举元数据的提取引擎

选项列表的生成依赖EnumHelper<TEnum>(见 EnumHelper.cs)。它的静态构造函数会完成一次性初始化:

static EnumHelper() { _enumType = THelper.GetUnderlyingType<T>(); _aggregateFunction = BuildAggregateFunction(); _valueList = Enum.GetValues(_enumType).Cast<T>(); _valueLabelList = _valueList.Select(value => (value, EnumHelper.GetDisplayName(_enumType, value))); _isFlags = _enumType.GetCustomAttribute<FlagsAttribute>() != null; _hasFlagFunction = BuildHasFlagFunction(); }

EnumRadioGroup用到的关键方法是GetValueLabelList(),它返回IEnumerable<(T Value, string Label)>元组集合,Label 的生成规则在内部类EnumHelper.GetDisplayName中定义:

public static string GetDisplayName(Type enumType, object enumValue) { var enumName = Enum.GetName(enumType, enumValue); var fieldInfo = enumType.GetField(enumName); return fieldInfo.GetCustomAttribute<DisplayAttribute>(true)?.GetName() ?? enumName; }

由此可以明确两点行为:

  • 优先取[Display(Name = "...")]:枚举成员标注了System.ComponentModel.DataAnnotations.Display特性时,单选框标签使用特性的Name值(示例中即 "🍎 Apple");
  • 缺省回退到成员名:未标注特性的成员(如示例的Pear、Orange)直接使用枚举成员名作为标签。

顺带说明,EnumHelper<TEnum>还提供GetValueList()、Combine()、Split()、IsFlags等能力,前者用于纯值列表,后两者面向[Flags]枚举的按位合并与拆分,是组件库在表单、级联等场景中复用的通用工具。

2.3 RadioGroup 的选项渲染管道

Options参数的类型是OneOf<string[], RadioOption<TValue>[]>(见 RadioGroup.razor.cs),支持两种形态:

形态说明渲染方式
string[]纯字符串数组每个字符串既作为Value又作为标签,如Options="@new string[]{"Apple","Pear"}"
RadioOption<TValue>[]值 + 标签(+ 可选 Disabled)结构用radio.Value作为值、radio.Label作为显示文本

RadioOption<TValue>的定义见 RadioOption.cs,包含Label、Value、Disabled三个属性。EnumRadioGroup选择的是第二种形态,把枚举值包装成RadioOption<TEnum>数组。

当Options与ChildContent同时存在时,渲染模板优先走Options分支,因此EnumRadioGroup内部无需关心子内容渲染。

三、关键参数与行为详解

由于EnumRadioGroup<TEnum>直接继承RadioGroup<TValue>,以下参数全部可用,参数声明均可在 RadioGroup.razor.cs 中查到:

参数类型默认值说明
TEnum泛型参数-指定要渲染的枚举类型,必须有值
Value/@bind-ValueTEnum-当前选中值,双向绑定;DefaultValue可单独指定初始值
DefaultValueTEnum-默认选中值,设置后会同步到CurrentValue
Disabledboolfalse禁用整组单选框,会联动所有子Radio的禁用状态
ButtonStyleRadioButtonStyle?Outline按钮风格,Outline(描边)或Solid(填色),枚举定义见 ButtonStyle.cs
Namestring自动生成组内所有input[type="radio"]的 name 属性;为空时自动用ComponentIdGenerator生成
SizeInputSizeDefault大小,仅对按钮样式生效
OnChangeEventCallback<TEnum>-选中值变化后的回调,仅在值真正变化时触发

两个值得展开的源码行为:

  • Disabled 的联动机制:RadioGroup.OnInitialized中调用AddRadio注册每个子单选框(见 RadioGroup.razor.cs),若当前Disabled为 true,会通过radio.SetDisabledValue(_disabled)与OnDisabledValueChanged事件同步给所有子项;若某个子项自身已禁用,则不会被组级状态覆盖。
  • Name 的自动生成:当Name未显式指定时,OnInitialized会回退到NameAttributeValue ?? PropertyName ?? ComponentIdGenerator.Generate(this),确保同组单选互斥的 name 语义始终成立。

OnChange的触发逻辑也值得注意(见 RadioGroup.razor.cs):内部先比较新旧值,仅在EqualsValue(oldValue, CurrentValue)为 false 时才InvokeAsync,避免重复回调。

四、从"值列表"到"自定义标签":与 Options 方式的对照

EnumRadioGroup本质上是"枚举 → Options"的语法糖。如果你不想引入枚举,可以手动构造等价的RadioOption<TEnum>[],参考同目录下的 Optional.razor:

RadioOption<string>[] options2 = new RadioOption<string>[] { new(){ Value = "Apple", Label="🍎 Apple", }, new(){ Value = "Pear", Label="🍐 Pear", }, new(){ Value = "Orange", Label="🍊 Orange", }, }; <RadioGroup Options="@options2" @bind-Value="_radioValue" ButtonStyle="RadioButtonStyle.Outline"></RadioGroup>

两种方式的差异可以总结为:

维度EnumRadioGroup<TEnum>RadioGroup+Options
选项来源枚举类型自动提取手动构造数组
标签自定义通过[Display(Name)]特性通过RadioOption.Label
值类型约束必须是枚举类型TEnum任意TValue(string、int、bool 等均可)
适用场景选项与业务枚举一一对应、且需要类型安全选项动态变化、来源为数据或配置

因此,当你的选项集合天然对应一个枚举(如状态、类型、方向、对齐方式),优先使用EnumRadioGroup,既能省去手写RadioOption数组的样板代码,又能获得编译期类型安全的@bind-Value绑定;而选项来自数据库、接口等动态数据时,则应使用Options或ChildContent方式。

五、项目实战案例:用枚举单选框控制 Table 列对齐

EnumRadioGroup不仅在 Radio 组件 demo 中出现,也被组件库自身的文档站点复用。在 Table 组件的 ColumnAlignment.razor 示例中,列对齐方式的选择就是通过枚举单选框实现的:

<p>Column alignment: @columnAlign</p> <EnumRadioGroup TEnum="ColumnAlign" @bind-Value="@columnAlign" /> @code{ ColumnAlign columnAlign = ColumnAlign.Left; ... }

随后这个columnAlign变量被直接传给多个PropertyColumn的Align属性,实现"切换对齐方式 → 表格列实时重排"的联动效果。这个案例说明了两点:

  1. EnumRadioGroup适合作为设置面板 / 工具栏中的枚举型选项选择器,绑定一个字段即可完成 UI 与状态的同步;
  2. 由于@bind-Value的泛型类型就是枚举本身,值可以直接参与业务逻辑判断,无需再做字符串转换。

六、小结

EnumRadioGroup<TEnum>是 ant-design-blazor 中"声明式 UI"思想的典型体现:通过EnumHelper<TEnum>在构造函数期将枚举元数据(值 +Display标签)转换为RadioOption<TEnum>[],再复用RadioGroup<TValue>完整的Options渲染管道与参数体系(Disabled、ButtonStyle、Name、Size、OnChange、双向绑定等),让"定义一个枚举、渲染一组单选框"成为一行代码即可完成的操作。

如需进一步探索,可以依次阅读:

  • 组件 demo:EnumGroup.razor 与 enum-group.md;
  • 组件实现:EnumRadioGroup.cs、RadioGroup.razor.cs、RadioGroup.razor、RadioOption.cs;
  • 枚举工具:EnumHelper.cs;
  • 同类组件对比:EnumSelect(EnumSelect.cs)、EnumCheckboxGroup(EnumCheckboxGroup.cs)在 Select、Checkbox 场景下提供了同样的枚举驱动能力。
  • UI组件
  • 前端

【免费下载链接】ant-design-blazor

🌈A rich set of enterprise-class UI components based on Ant Design and Blazor.

项目地址:https://gitcode.com/gh_mirrors/an/ant-design-blazor
点击查看免费下载
上一篇:终极指南:如何使用Hoppscotch打造无障碍API开发环境
下一篇:claude-seo 语义主题聚类实战:用 SERP 重叠数据驱动 Hub-and-Spoke 内容架构规划

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询