How to have userfriendly names for enumerations?(如何为枚举使用用户友好的名称?)
问题描述
我有一个像
Enum Complexity
{
NotSoComplex,
LittleComplex,
Complex,
VeryComplex
}
我想在下拉列表中使用它,但不想在列表中看到这样的 Camel 名称(对于用户来说看起来很奇怪).相反,我想用正常的措辞,比如没那么复杂小复杂(等)
And I want to use it in a dropdown list, but don't want to see such Camel names in list (looks really odd for users). Instead I would like to have in normal wording, like Not so complex Little complex (etc)
另外,我的应用程序是多语言的,我希望能够显示那些本地化的字符串,我使用了一个助手 TranslationHelper(string strID),它为我提供了字符串 id 的本地化版本.
Also, my application is multi-lang and I would like to be able to display those strings localized, and I use a helper, TranslationHelper(string strID) which gives me the localized version for a string id.
我有一个可行的解决方案,但不是很优雅:我为枚举创建了一个辅助类,其中一个成员 Complexity 和 ToString() 被覆盖,如下所示(代码简化)
I have a working solution, but not very elegant: I create a helper class for the enum, with one member Complexity and ToString() overwritten, like below (code simplified)
public class ComplexityHelper
{
public ComplexityHelper(Complexity c, string desc)
{ m_complex = c; m_desc=desc; }
public Complexity Complexity { get { ... } set {...} }
public override ToString() { return m_desc; }
//Then a static field like this
private static List<Complexity> m_cxList = null;
// and method that returns the status lists to bind to DataSource of lists
public static List<ComplexityHelper> GetComplexities()
{
if (m_cxList == null)
{
string[] list = TranslationHelper.GetTranslation("item_Complexities").Split(',');
Array listVal = Enum.GetValues(typeof(Complexities));
if (list.Length != listVal.Length)
throw new Exception("Invalid Complexities translations (item_Complexities)");
m_cxList = new List<Complexity>();
for (int i = 0; i < list.Length; i++)
{
Complexity cx = (ComplexitylistVal.GetValue(i);
ComplexityHelper ch = new ComplexityHelper(cx, list[i]);
m_cxList.Add(ch);
}
}
return m_cxList;
}
}
虽然可行,但我对此并不满意,因为我必须为我需要在选项列表中使用的各种枚举进行类似的编码.
While workable, I'm not happy with it, since I have to code it similarily for various enums I need to use in picklists.
有人对更简单或更通用的解决方案有建议吗?
Does anyone have a suggestion for a simpler or more generic solution?
谢谢波格丹
推荐答案
谢谢大家的回答.最后,我使用了 Rex M 和 adrianbanks 的组合,并添加了我自己的改进,以简化与 ComboBox 的绑定.
Thank you all for all answers. Finally I used a combination from Rex M and adrianbanks, and added my own improvements, to simplify the binding to ComboBox.
之所以需要更改,是因为在处理代码时,我意识到有时我需要能够从组合中排除一个枚举项.例如.
The changes were needed because, while working on the code, I realized sometimes I need to be able to exclude one enumeration item from the combo. E.g.
Enum Complexity
{
// this will be used in filters,
// but not in module where I have to assign Complexity to a field
AllComplexities,
NotSoComplex,
LittleComplex,
Complex,
VeryComplex
}
所以有时我希望选择列表显示除 AllComplexities 之外的所有内容(在添加 - 编辑模块中),而其他时候显示所有内容(在过滤器中)
So sometimes I want the picklist to show all but AllComplexities (in add - edit modules) and other time to show all (in filters)
这就是我所做的:
- 我创建了一个扩展方法,它使用描述属性作为本地化查找键.如果缺少描述属性,我将查找本地化键创建为 EnumName_枚举值.最后,如果缺少翻译,我只是将基于驼峰式的枚举名称拆分为分隔单词,如 adrianbanks 所示.顺便说一句,TranslationHelper 是 resourceMgr.GetString(...) 的包装器
完整代码如下所示
public static string GetDescription(this System.Enum value)
{
string enumID = string.Empty;
string enumDesc = string.Empty;
try
{
// try to lookup Description attribute
FieldInfo field = value.GetType().GetField(value.ToString());
object[] attribs = field.GetCustomAttributes(typeof(DescriptionAttribute), true);
if (attribs.Length > 0)
{
enumID = ((DescriptionAttribute)attribs[0]).Description;
enumDesc = TranslationHelper.GetTranslation(enumID);
}
if (string.IsNullOrEmpty(enumID) || TranslationHelper.IsTranslationMissing(enumDesc))
{
// try to lookup translation from EnumName_EnumValue
string[] enumName = value.GetType().ToString().Split('.');
enumID = string.Format("{0}_{1}", enumName[enumName.Length - 1], value.ToString());
enumDesc = TranslationHelper.GetTranslation(enumID);
if (TranslationHelper.IsTranslationMissing(enumDesc))
enumDesc = string.Empty;
}
// try to format CamelCase to proper names
if (string.IsNullOrEmpty(enumDesc))
{
Regex capitalLetterMatch = new Regex("\B[A-Z]", RegexOptions.Compiled);
enumDesc = capitalLetterMatch.Replace(value.ToString(), " $&");
}
}
catch (Exception)
{
// if any error, fallback to string value
enumDesc = value.ToString();
}
return enumDesc;
}
我创建了一个基于 Enum 的通用帮助类,它允许将枚举轻松绑定到 DataSource
I created a generic helper class based on Enum, which allow to bind the enum easily to DataSource
public class LocalizableEnum
{
/// <summary>
/// Column names exposed by LocalizableEnum
/// </summary>
public class ColumnNames
{
public const string ID = "EnumValue";
public const string EntityValue = "EnumDescription";
}
}
public class LocalizableEnum<T>
{
private T m_ItemVal;
private string m_ItemDesc;
public LocalizableEnum(T id)
{
System.Enum idEnum = id as System.Enum;
if (idEnum == null)
throw new ArgumentException(string.Format("Type {0} is not enum", id.ToString()));
else
{
m_ItemVal = id;
m_ItemDesc = idEnum.GetDescription();
}
}
public override string ToString()
{
return m_ItemDesc;
}
public T EnumValue
{
get { return m_ID; }
}
public string EnumDescription
{
get { return ToString(); }
}
}
然后我创建了一个通用的静态方法,它返回一个 List>,如下所示
Then I created a generic static method that returns a List>, as below
public static List<LocalizableEnum<T>> GetEnumList<T>(object excludeMember)
{
List<LocalizableEnum<T>> list =null;
Array listVal = System.Enum.GetValues(typeof(T));
if (listVal.Length>0)
{
string excludedValStr = string.Empty;
if (excludeMember != null)
excludedValStr = ((T)excludeMember).ToString();
list = new List<LocalizableEnum<T>>();
for (int i = 0; i < listVal.Length; i++)
{
T currentVal = (T)listVal.GetValue(i);
if (excludedValStr != currentVal.ToString())
{
System.Enum enumVal = currentVal as System.Enum;
LocalizableEnum<T> enumMember = new LocalizableEnum<T>(currentVal);
list.Add(enumMember);
}
}
}
return list;
}
和一个包含所有成员的返回列表的包装器
and a wrapper to return list with all members
public static List<LocalizableEnum<T>> GetEnumList<T>()
{
return GetEnumList<T>(null);
}
现在让我们把所有东西放在一起并绑定到实际的组合:
Now let's put all things together and bind to actual combo:
// in module where we want to show items with all complexities
// or just filter on one complexity
comboComplexity.DisplayMember = LocalizableEnum.ColumnNames.EnumValue;
comboComplexity.ValueMember = LocalizableEnum.ColumnNames.EnumDescription;
comboComplexity.DataSource = EnumHelper.GetEnumList<Complexity>();
comboComplexity.SelectedValue = Complexity.AllComplexities;
// ....
// and here in edit module where we don't want to see "All Complexities"
comboComplexity.DisplayMember = LocalizableEnum.ColumnNames.EnumValue;
comboComplexity.ValueMember = LocalizableEnum.ColumnNames.EnumDescription;
comboComplexity.DataSource = EnumHelper.GetEnumList<Complexity>(Complexity.AllComplexities);
comboComplexity.SelectedValue = Complexity.VeryComplex; // set default value
要读取选定的值并使用它,我使用如下代码
To read selected the value and use it, I use code as below
Complexity selComplexity = (Complexity)comboComplexity.SelectedValue;
这篇关于如何为枚举使用用户友好的名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何为枚举使用用户友好的名称?
基础教程推荐
- MS Visual Studio .NET 的替代品 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- c# Math.Sqrt 实现 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- 如何激活MC67中的红灯 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- rabbitmq 的 REST API 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01