我想要使用enum
从C#中的ComboBox
中选择值,或者选择位掩码(对于enum
属性为Flags
)并使用{{1} }。我想要一种方法将值添加到控件作为可选项,并干净地告诉用户选择了哪些。
我还希望选择对用户来说清晰而美观。目前,我已经可以将CheckedListBox
值添加到Enum
或ComboBox
,但CheckedListBox
将返回标识符名称。 Pascal Case对我来说已经足够了,但不适合我的用户。
我希望这很容易编码。我的意思是容易。我希望这只是在定义和/或使用任何 Enum.ToString()
值时的事后想法。
现在我环顾四周,看到了几个不错的解决方案。其中一些以自己的方式更好,例如if you really need to put in your own custom descriptions,或者更进一步,support multiple languages。你也可以做fake enums。但是我一直在寻找,并且没有一个像我所写的那样,为了我的目的而优雅和简单的结合。见下文。
答案 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
。Enum
值,但有一些特殊情况。一个示例可能是名为MyValue__DescriptionOf123_ENUMValue
的值,它将来自ToStringFriendly()
“我的价值:123-ENUM值的描述”。struct
和一个扩展方法)可以写一次并隐藏起来。每个Enum
都没有其他编码。这意味着它可以很好地用于用于你没有编写的枚举,假设Pascal情况,在.NET中是一个很好的假设。 注意:这就是为什么我会说this answer,虽然优雅,但不是比我更好的解决方案,因为它要求您可以为每个TypeConverter
添加Enum
属性 Encoding.EBCDIC
这样的值将始终作为“EBCDIC”出现,并且不允许您手动键入“扩展二进制编码的十进制交换代码”,更不用说其他语言了。可以通过在de-Pascal-casing之前更改ToStringFriendly()
来为该值执行语言查找来添加自定义描述和多语言支持。
有关正则表达式的更多乐趣,请参阅this thread。