1

这只是对在ComboBox源自Enum.

我知道我可以将 a 数据绑定ComboBoxEnum这样的:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        comboBoxNames.DataSource = Enum.GetValues(typeof (Names));
    }
}

public enum Names
{
    JohnDoe,
    JaneDoe,
    JohnJackson,
    JackJohnson
}

这是结果:

在此处输入图像描述

我想格式化显示值,ComboBox使得 PascalCase 字符串值之间有一个空格,同时还传递Enum我可以在switch稍后的语句中使用的所选项目的值:

switch ((Names)comboBoxNames.SelectedItem)
{
    case Names.JohnDoe:
        // Do something John Doe-specific
        break;
    case Names.JaneDoe:
        // Do something Jane Doe-specific
        break;
    case Names.JohnJackson:
        // Do something John Jackson-specific
        break;
    case Names.JackJohnson:
        // Do something Jack Johnson-specific
        break;
}

我知道有一个ComboBox.FormatString属性,但我不确定如何使用它来Names按照我想要的方式格式化枚举。

这可能吗?我宁愿不使用属性,Enum因为使用它最终涉及使用反射,这对于看起来如此简单的事情来说似乎有点过分了。任何帮助将非常感激。

4

2 回答 2

1

这很简单,只需在您的组合框上添加格式事件并使其看起来像这样:

private void comboBoxNames_Format(object sender, ListControlConvertEventArgs e)
{
    StringBuilder newText = new StringBuilder(e.Value.ToString().Length +1);
    newText.Append(e.Value.ToString()[0]);
    for (int i = 1; i < e.Value.ToString().Length; i++)
    {
        if (char.IsUpper(e.Value.ToString()[i]) && e.Value.ToString()[i - 1] != ' ')
            newText.Append(' ');
        newText.Append(e.Value.ToString()[i]);
    }
    e.Value = newText.ToString();
}
于 2013-04-04T19:35:19.953 回答
0

我想出了一种方法来格式化ComboBox源自Enum我喜欢的 a 的字符串值,而不需要ComboBox.FormatString属性或Format事件:使用Dictionary<Enum, string>. 下面的示例代码:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    protected override void OnLoad(EventArgs e)
    {
        comboBoxNames.DataBindToEnum(default(Names).ToDictionary());
    }

    private void btnOK_Click(object sender, EventArgs e)
    {
        switch (((KeyValuePair<Names, string>)comboBoxNames.SelectedItem).Key)
        {
            case Names.JohnDoe:
                // Do something John Doe-specific
                MessageBox.Show(@"John Doe!");
                break;
            case Names.JaneDoe:
                // Do something Jane Doe-specific
                MessageBox.Show(@"Jane Doe!");
                break;
            case Names.JohnJackson:
                // Do something John Jackson-specific
                MessageBox.Show(@"John Jackson!");
                break;
            case Names.JackJohnson:
                // Do something Jack Johnson-specific
                MessageBox.Show(@"Jack Johnson!");
                break;
        }
    }
}

public enum Names
{
    JohnDoe,
    JaneDoe,
    JohnJackson,
    JackJohnson
}

public static class EnumExtensions
{
    public static Dictionary<T, string> ToDictionary<T>(this T enumeration)
    {
        if (!enumeration.GetType().IsEnum) return null;

        var enumValues = Enum.GetValues(typeof(T)).OfType<T>().ToList();
        return enumValues.ToDictionary(enumValue => enumValue, enumValue => enumValue.ToString().Spaceify());
    }
}

public static class StringExtensions
{
    public static string Spaceify(this string self)
    {
        for (var i = 1; i < self.Length - 1; i++)
        {
            if (char.IsLower(self[i - 1]) && char.IsUpper(self[i]) ||
                self[i - 1] != ' ' && char.IsUpper(self[i]) && char.IsLower(self[i + 1]))
            {
                self = self.Insert(i, " ");
            }
        }
        return self;
    }
}

public static class ControlExtensions
{
    public static void DataBindToEnum<T>(this ListControl listControl, IDictionary<T, string> enumAsDictionary)
    {
        listControl.DataSource = new BindingSource(enumAsDictionary, null);
        listControl.DisplayMember = "Value";
        listControl.ValueMember = "Key";
    }
}

有几点需要注意:

  • 不要ComboBox.DataSource直接将 设置为 的列表enum,而是使用 a 设置它并相应Dictionary<Enum, string>地设置and (扩展方法)DisplayMemberValueMemberDataBindToEnum
  • 目前我们不能使用enum关键字作为类型限制(类似public static Dictionary<T, string> ToDictionary<T>(this T enumeration) **where T : enum**)。这就是为什么enum需要在该方法的主体中进行检查的原因
  • Spaceify扩展方法将空格添加到 PascalCase 字符串(也处理首字母缩略词)
  • “魔术”行是我使用default关键字的地方,enum以便我可以将其作为列表类型对象处理并解决在“实例”的“实例”上调用方法的问题enum
  • 最后,当使用 out 时,ComboBox.SelectedItem我需要将其转换为 aKeyValuePair<Enum, string>并拉出Key我可以在我的switch语句中使用的。没有更多的魔术字符串!

希望这可以帮助!

于 2013-04-08T08:30:57.907 回答