在.NET开发中,枚举(enum)是一种常用的数据类型,用于定义一组命名的常量。然而,直接使用枚举值进行数据绑定时,可能会遇到两个问题:一是枚举值的显示文本可能需要与实际的枚举值有所区别,二是如果需要对应用程序进行本地化,即提供不同文化的翻译界面,直接使用枚举值就无法满足需求。本文将介绍一种利用.NET的TypeConverter机制来解决这些问题的方法。
在.NET中,TypeConverter是用于将一种类型的对象转换为另一种类型的对象的内置机制。例如,ListBox控件在显示枚举值时,会首先使用TypeConverter将枚举值转换为字符串。默认情况下,所有枚举类型都使用预定义的EnumConverter类,它将枚举值转换为其精确的字符串表示。幸运的是,可以定义自己的派生TypeConverter类,并将其与枚举类型关联起来。
在.NET中,TypeConverter是用于将一种类型的对象转换为另一种类型的对象的内置机制。例如,ListBox控件在显示枚举值时,会首先使用TypeConverter将枚举值转换为字符串。默认情况下,所有枚举类型都使用预定义的EnumConverter类,它将枚举值转换为其精确的字符串表示。幸运的是,可以定义自己的派生TypeConverter类,并将其与枚举类型关联起来。
要自定义TypeConverter,需要定义一个继承自TypeConverter的类,并使用System.ComponentModel.TypeConverterAttribute属性将其与枚举类型关联。以下是一个示例:
[TypeConverter(typeof(LocalizedEnumConverter))]
public enum SampleEnum
{
VerySmall,
Small,
Medium,
Large,
VeryLarge
}
在这个解决方案中,定义了一个自定义的TypeConverter类(LocalizedEnumConverter),它使用项目资源中的本地化字符串将枚举值转换为字符串。
示例项目代码包括一个库(Infralution.Localization)和一个单独的测试应用程序。该库定义了一个基础TypeConverter类(ResourceEnumConverter),它使用ResourceManager从编译的RESX文件中读取字符串值。ResourceManager用于查找的构造函数传递给ResourceEnumConverter类。以下是使用此类本地化应用程序中的枚举的简单步骤。
class LocalizedEnumConverter : Infralution.Localization.ResourceEnumConverter
{
public LocalizedEnumConverter(Type type)
: base(type, Properties.Resources.ResourceManager)
{
}
}
[TypeConverter(typeof(LocalizedEnumConverter))]
public enum SampleEnum
{
VerySmall,
Small,
Medium,
Large,
VeryLarge
}
在Windows Forms中,所有标准控件都使用TypeConverters将绑定的数据值转换为显示字符串。不幸的是,出于某种原因,Microsoft在开发ASP.NET控件时没有采用这种方法。ASP.NET控件通常只使用Object.ToString()方法将绑定的数据值转换为文本。这意味着虽然仍然可以定义TypeConverter(如上所述),但它不会默认被ASP.NET控件使用。
为了解决这个问题,在ResourceEnumConverter类中添加了一个静态GetValues方法。该方法使用TypeConverter返回给定枚举类型的KeyValuePair对象列表。Key是枚举值,Value是该枚举的本地化显示文本。要绑定ASP.NET控件,将控件的DataValueField属性设置为Key,DataTextField属性设置为Value。然后绑定控件到GetValues方法返回的列表,如下所示:
protected void Page_Load(object sender, EventArgs e)
{
_enumListBox.DataSource = LocalizedEnumConverter.GetValues(typeof(SampleEnum));
this.DataBind();
}
Andy Mase指出,原始代码没有处理位字段枚举(使用Flag属性定义)。在这种情况下,枚举值可以是命名枚举值的位组合。枚举还可以定义命名枚举值,这些值是其他命名值的位组合。以下示例中定义了一个All值,它是所有其他值的位组合:
[TypeConverter(typeof(LocalizedEnumConverter))]
[Flags]
public enum TextStyle : byte
{
None = 0x0,
Bold = 0x1,
Italic = 0x2,
Underline = 0x4,
All = 0xFF
}