EnumButtonGroup:绑定枚举值到按钮的替代方案






4.47/5 (7投票s)
一个 Windows Forms 用户控件,允许在设计时和运行时将枚举值绑定到一组按钮。

引言
你可以使用 Visual Studio 捆绑提供的 Windows Forms 控件做很多很酷的事情。不幸的是,将枚举值绑定到一组按钮并不是其中之一。本文介绍了一种旨在实现此目的的控件。
背景
前几天我在工作时拼凑一个快速原型时,我意识到我需要一个控件,我可以用来将枚举值显示为单选按钮。我不记得 Visual Studio 中有任何内置的可以做到这一点的功能,所以我做了一个快速的在线搜索。我找到的最接近我想要的东西是 Jay Andrew Allen 的这篇 文章。然而,他的控件不允许我指定我想要显示的枚举类型,并让控件自动为我创建按钮。几个小时后,我创建了想要的控件。
Using the Code
EnumButtonGroup
控件是一个 Windows Forms UserControl
,它公开了额外的属性 ValueType
和 SelectedValue
以及一个 SelectedValueChanged
事件。
ValueType
属性用于指定表示将在控件中显示的枚举值的 .NET Type
。
[TypeConverter(typeof(StringToTypeConverter))]
public Type ValueType
{
get
{
return (this.valueType);
}
set
{
// Make sure value is an enumerated type
if (value != null && !value.IsEnum)
{
throw new ArgumentException("Argument must be an enumerated type");
}
this.valueType = value;
if (this.valueType == null)
{
// Reset
this.Controls.Clear();
this.Controls.Add(this.placeholderLabel);
this.selectedValue = null;
RaiseSelectedValueChangedEvent();
}
else
{
// Create button controls based on new valueType
CreateButtons();
}
}
}
设置此属性时,控件首先检查它是否表示枚举类型。如果是,它会自动创建表示该枚举类型的值的按钮。然后将 SelectedValue
属性设置为第一个枚举值,并通过 SelectedValueChanged
事件通知任何订阅者。
SelectedValue
属性用于指定将在控件中显示的枚举值中的哪一个将被选中(选中)。
[Editor(typeof(EnumButtonGroupSelectedValueEditor), typeof(UITypeEditor))]
public object SelectedValue
{
get
{
return (this.selectedValue);
}
set
{
// Don't bother setting if valueType is unknown
if (this.valueType != null)
{
this.selectedValue = value;
// If we are here as a result of a button CheckedChanged event
// then there is no need to check the button
if (!this.alreadyChecked)
{
CheckButton();
}
else
{
// Tell everyone the selected value has changed
RaiseSelectedValueChangedEvent();
}
}
}
}
当 SelectedValue
属性响应来自某个按钮的 CheckChanged
事件自动设置时,控件只需通过 SelectedValueChanged
事件通知任何订阅者该更改。如果直接设置该属性,则会将相应按钮的 Checked
属性设置为 true
,这反过来会导致引发 SelectedValueChanged
事件。
希望在 SelectedValue
属性更改时收到通知的应用程序应注册以接收 SelectedValueChanged
事件。
public void MainForm_Load(object sender, EventArgs e)
{
this.enumButtonGroup1.SelectedValueChanged +=
new EventHandler(enumButtonGroup1_SelectedValueChanged);
}
...
private void enumButtonGroup1_SelectedValueChanged(object sender, EventArgs e)
{
this.propertyGrid1.SelectedObject = sender;
}
设计时注意事项
我希望 ValueType
属性在设计时和运行时都可以编辑。为了启用此功能,我需要添加一个类型转换器 (StringToTypeConverter
) 将 string
转换为 Type
,从而允许以 string
格式指定 ValueType
。
一个特别需要注意的点:如果该类型不在应用程序加载的程序集中或在 mscorlib.dll 程序集中,则 Type.GetType()
方法将返回 null
。
我还希望 SelectedValue
属性在设计时可编辑。这意味着我需要添加一个 UI 类型编辑器 (EnumButtonGroupSelectedValueEditor
) 来显示可供选择的可能值的下拉列表。

关注点
您可能已经注意到我还添加了一些其他属性
Orientation
是一个枚举值,允许按钮在控件中水平或垂直方向排列ShowDescriptions
是一个布尔属性,用于控制是否显示使用DescriptionAttribute
标记的枚举值的描述HideObsoleteValues
是一个布尔属性,用于控制是否显示使用ObsoleteAttribute
标记的枚举值
一些可能的补充功能将使此控件更有用
- 指定不同的布局,允许将按钮排列成行和列
- 将使用
FlagsAttribute
标记的枚举值显示为复选框
附加的项目是一个 Visual Studio 2008 / .NET 3.5 项目。如果有人想要 Visual Studio 2005 / .NET 2.0 版本,请告诉我,我会上传一个。
历史
- 2008 年 12 月 6 日:首次提交
- 2008 年 12 月 9 日:添加了 Visual Studio 2005 版本。将
ShowObsoleteValues
重命名为HideObsoleteValues
以更正反向逻辑错误。
这是我的第一篇文章提交。我将感谢任何反馈。