65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (7投票s)

2008年12月6日

CPOL

3分钟阅读

viewsIcon

30134

downloadIcon

340

一个 Windows Forms 用户控件,允许在设计时和运行时将枚举值绑定到一组按钮。

runtime-horizontal.png

runtime-vertical-dayofweek.png

引言

你可以使用 Visual Studio 捆绑提供的 Windows Forms 控件做很多很酷的事情。不幸的是,将枚举值绑定到一组按钮并不是其中之一。本文介绍了一种旨在实现此目的的控件。

背景

前几天我在工作时拼凑一个快速原型时,我意识到我需要一个控件,我可以用来将枚举值显示为单选按钮。我不记得 Visual Studio 中有任何内置的可以做到这一点的功能,所以我做了一个快速的在线搜索。我找到的最接近我想要的东西是 Jay Andrew Allen 的这篇 文章。然而,他的控件不允许我指定我想要显示的枚举类型,并让控件自动为我创建按钮。几个小时后,我创建了想要的控件。

Using the Code

EnumButtonGroup 控件是一个 Windows Forms UserControl,它公开了额外的属性 ValueTypeSelectedValue 以及一个 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) 来显示可供选择的可能值的下拉列表。

designtime-vertical.png

关注点

您可能已经注意到我还添加了一些其他属性

  • 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 以更正反向逻辑错误。

这是我的第一篇文章提交。我将感谢任何反馈。

© . All rights reserved.