友元格式枚举用于ComboBoxes,CheckedListBoxes等

时间:2014-09-09 19:04:14

标签: c# listview combobox enums checkedlistbox

要求

我想要使用enum从C#中的ComboBox中选择值,或者选择位掩码(对于enum属性为Flags)并使用{{1} }。我想要一种方法将值添加到控件作为可选项,并干净地告诉用户选择了哪些。

目标1:用户友好

我还希望选择对用户来说清晰而美观。目前,我已经可以将CheckedListBox值添加到EnumComboBox,但CheckedListBox将返回标识符名称。 Pascal Case对我来说已经足够了,但不适合我的用户。

目标2:易于编码

我希望这很容易编码。我的意思是容易。我希望这只是在定义和/或使用任何 Enum.ToString()值时的事后想法。

我的解决方案

现在我环顾四周,看到了几个不错的解决方案。其中一些以自己的方式更好,例如if you really need to put in your own custom descriptions,或者更进一步,support multiple languages。你也可以做fake enums。但是我一直在寻找,并且没有一个像我所写的那样,为了我的目的而优雅和简单的结合。见下文。

1 个答案:

答案 0 :(得分:0)

我的解决方案的基础是struct,它可以包含Enum值并覆盖ToString()

输入EnumWrapper

public struct EnumWrapper
{
    private readonly Enum e;
    public EnumWrapper(Enum e) {
        this.e = e;
    }
    public static implicit operator Enum(EnumWrapper wrapper) {
        return wrapper.e;
    }
    public static explicit operator EnumWrapper(Enum e) {
        return new EnumWrapper(e);
    }
    public override string ToString() {
        return e.ToStringFriendly();
    }
}

方法ToStringFriendly()被定义为Enum上的扩展方法:

using System.Text.RegularExpressions;
public static class _Extensions
{
    public static string ToStringFriendly(this Enum e)
    {
        string s = e.ToString();

        // enforce a charset: letters, numbers, and underscores
        s = Regex.Replace(s, "[^A-Za-z0-9_]", ""); 

        // separate numbers from letters
        s = Regex.Replace(s, "([a-zA-Z])([0-9])", "$1 $2"); 

        // separate letters from numbers
        s = Regex.Replace(s, "([0-9])([a-zA-Z])", "$1 $2"); 

        // space lowercases before uppercase (word boundary)
        s = Regex.Replace(s, "([a-z])([A-Z])", "$1 $2"); 

        // see that the nice pretty capitalized words are spaced left
        s = Regex.Replace(s, "(?!^)([^ _])([A-Z][a-z]+)", "$1 $2"); 

        // replace double underscores with colon-space delimiter
        s = Regex.Replace(s, "__", ": "); 

        // finally replace single underscores with hyphens
        s = Regex.Replace(s, "_", "-"); 

        return s;
    }
}

现在,要向ComboBox添加任何Enum值,例如

comboBox.Items.Add((EnumWrapper)MyEnum.SomeValue);

然后将其取消(当然,在进行空值测试之后):

MyEnum myValue = (MyEnum)(Enum)(EnumWrapper)comboBox.SelectedItem;

就是这样。现在这种方法的优点和缺点是什么?

优点:

  • 您可以直接将控件中的枚举值(几乎)传入和传出。只需来回转动EnumWrapper
  • 这适用于所有Pascal-case Enum值,但有一些特殊情况。一个示例可能是名为MyValue__DescriptionOf123_ENUMValue的值,它将来自ToStringFriendly() “我的价值:123-ENUM值的描述”
  • 机制(一个struct和一个扩展方法)可以写一次并隐藏起来。每个Enum都没有其他编码。这意味着它可以很好地用于用于你没有编写的枚举,假设Pascal情况,在.NET中是一个很好的假设。 注意:这就是为什么我会说this answer,虽然优雅,但不是比我更好的解决方案,因为它要求您可以为每个TypeConverter添加Enum属性

缺点:

  • 这不支持自定义说明多种语言。例如,像Encoding.EBCDIC这样的值将始终作为“EBCDIC”出现,并且不允许您手动键入“扩展二进制编码的十进制交换代码”,更不用说其他语言了。

未来工作

可以通过在de-Pascal-casing之前更改ToStringFriendly()来为该值执行语言查找来添加自定义描述和多语言支持。

有关正则表达式的更多乐趣,请参阅this thread