Vb.net 将枚举的所有描述绑定到组合框
如何将枚举的格式化字符串描述绑定到组合框?我希望组合框显示描述,而不是枚举 我有这样一个枚举:Vb.net 将枚举的所有描述绑定到组合框,vb.net,enums,combobox,Vb.net,Enums,Combobox,如何将枚举的格式化字符串描述绑定到组合框?我希望组合框显示描述,而不是枚举 我有这样一个枚举: Public Enum Sandwiches <ComponentModel.Description("Ham Sandwich")> HamSandwich <ComponentModel.Description("Reuben")> Reuben <ComponentModel.Description("Po’ Boy
Public Enum Sandwiches
<ComponentModel.Description("Ham Sandwich")> HamSandwich
<ComponentModel.Description("Reuben")> Reuben
<ComponentModel.Description("Po’ Boy")> PoBoy
<ComponentModel.Description("Grilled Cheese")> GrilledCheese
End Enum
公共枚举三明治
火腿三明治
鲁本
波博伊
烤奶酪
结束枚举
在描述字符串已绑定到组合框后,我可以使用此函数将选定项转换回枚举:
Public Function GetEnumFromDescriptionAttribute(Of T)(description As String) As T
Dim type As Type = GetType(T)
If Not type.IsEnum Then
Throw New InvalidOperationException()
End If
For Each fi As Reflection.FieldInfo In type.GetFields()
Dim descriptionAttribute As ComponentModel.DescriptionAttribute = TryCast(Attribute.GetCustomAttribute(fi, GetType(ComponentModel.DescriptionAttribute)), ComponentModel.DescriptionAttribute)
If descriptionAttribute IsNot Nothing Then
If descriptionAttribute.Description <> description Then
Continue For
End If
Return DirectCast(fi.GetValue(Nothing), T)
End If
If fi.Name <> description Then
Continue For
End If
Return DirectCast(fi.GetValue(Nothing), T)
Next
Return Nothing
End Function
公共函数GetEnumFromDescriptionAttribute(Of T)(描述为字符串)作为T
Dim type As type=GetType(T)
如果不是type.IsEnum,则
抛出新的InvalidOperationException()
如果结束
对于类型.GetFields()中的每个fi作为Reflection.FieldInfo
Dim descriptionAttribute As ComponentModel.descriptionAttribute=TryCast(Attribute.GetCustomAttribute(fi,GetType(ComponentModel.descriptionAttribute)),ComponentModel.descriptionAttribute)
如果descriptionAttribute不是空的,那么
如果为descriptionAttribute.Description,则为
继续
如果结束
返回DirectCast(fi.GetValue(Nothing),T)
如果结束
如果是fi.名称描述,则
继续
如果结束
返回DirectCast(fi.GetValue(Nothing),T)
下一个
一无所获
端函数
但是我找不到一种干净的方法将所有枚举绑定到combobox。我知道一个经常被建议的解决方案是将枚举和枚举描述转换为字典,然后将它们设置为cbo DisplayMember和ValueMember。但我不知道该怎么做
我已经准备好了几十个关于如何做到这一点的部分解决方案;问题是它们都是用C#编写的,在关闭Option Strict的情况下使用隐式转换,并且没有显示完整的实现。因此,我不可能将任何解决方案转换为.NET,因为我不知道变量定义为什么类型。这是我不久前编写的一个类,用于表示
Enum
值及其描述:
导入System.ComponentModel
输入系统。反射
'''
''包含枚举常量值和该值的友好描述(如果存在)。
'''
'''
''值的枚举类型。
'''
公共类枚举描述符(共T个)
'''
''对价值的友好描述。
'''
私有\u描述为字符串
'''
''枚举的常量值。
'''
私有值作为T
'''
''获取值的友好描述。
'''
'''
''一个字符串,包含值的描述属性值(如果存在);否则,将指定值名称。
'''
作为字符串的公共只读属性描述()
得到
给我回电话
结束
端属性
'''
''获取枚举的常量值。
'''
'''
''枚举描述符的泛型参数类型的枚举常量。
'''
作为T的公共只读属性值()
得到
返回给我
结束
端属性
'''
''创建EnumDescriptor类的新实例。
'''
'''
''提供描述的值。
'''
公共子新建(ByVal值为T)
我的价值=价值
'获取描述属性。
Dim字段为FieldInfo=value.GetType().GetField(value.ToString())
Dim属性作为DescriptionAttribute()=DirectCast(field.GetCustomAttributes(GetType(DescriptionAttribute))_
假),_
DescriptionAttribute())
'使用描述属性(如果存在),否则使用值本身作为描述。
Me.\u description=If(attributes.Length=0_
value.ToString()_
属性(0)。描述)
端接头
'''
“已覆盖”。创建对象的字符串表示形式。
'''
'''
''对价值的友好描述。
'''
Public将函数ToString()重写为字符串
还给我。描述
端函数
末级
这是我刚刚写的一个简化版本:
导入System.ComponentModel
输入系统。反射
公共类枚举描述符(共T个)
作为字符串的公共只读属性描述
公共只读属性值为T
公共子新建(值为T)
价值=价值
'获取描述属性。
Dim字段=value.GetType().GetField(value.ToString())
Dim attributes=DirectCast(field.GetCustomAttributes(GetType(DescriptionAttribute),False),DescriptionAttribute())
'如果存在描述属性,则使用该属性,否则使用值本身作为描述。
Description=If(attributes.Length=0,value.ToString(),attributes(0).Description)
端接头
Public将函数ToString()重写为字符串
返回说明
端函数
末级
下面是另一个类,可用于为枚举中的每个值存储前一个类的实例:
“”
''枚举类型的枚举描述符的集合。
'''
'''
''为其创建枚举描述符的枚举类型。
'''
公共类EnumDescriptorCollection(共T个)
继承ObjectModel.Collection(属于EnumDescriptor(属于T))
'''
''创建EnumDescriptorCollection类的新实例。
'''
公共分新()
'使用每个枚举值的枚举描述符填充集合。
对于[Enum].GetValues(GetType(T))中作为T的每个值
添加(新的枚举描述符(共T个)(值))
下一个
端接头
末级
Imports System.ComponentModel
Imports System.Globalization
Imports System.Reflection
Public Class EnumDescriptionConverter(Of T As {Structure, IConvertible}) : Inherits EnumConverter
Private enumDescriptions As New Dictionary(Of T, String)
Public Sub New()
MyBase.New(GetType(T))
' Since the ability to add an Enum constraint to the generic type does not exist in VB.
' this check is to ensure that it is an Enum.
' Note that normally, throwing an exception in a constructor is considered bad form, but
' there is no other option
If GetType(T).IsEnum Then
LoadEnumDescriptions()
Else
Throw New ArgumentException($"{GetType(T).Name} is not an Enum")
End If
End Sub
Private Sub LoadEnumDescriptions()
' An Enum type comprises static (Shared) fields that represent the defined enum values and
' an instance field that holds thae actual value. so only retrieve the static fields
' to get the defined (named) enum members.
For Each fi As FieldInfo In GetType(T).GetFields(BindingFlags.Public Or BindingFlags.Static)
Dim description As String
Dim descAttrib As DescriptionAttribute = fi.GetCustomAttribute(Of DescriptionAttribute)
If descAttrib Is Nothing Then
' no description attribute so use the defined name
description = fi.Name
Else
description = descAttrib.Description
End If
enumDescriptions.Add(CType(fi.GetValue(Nothing), T), description)
Next
End Sub
Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
Dim ret As Object
' the purpose of this converter is to provide an enum's description attribute as the string representation
' instead of the field name as provided by the standard implemention.
If destinationType Is GetType(String) AndAlso value IsNot Nothing Then
Dim enumValue As T = DirectCast(value, T)
If enumDescriptions.ContainsKey(enumValue) Then
ret = enumDescriptions(enumValue)
Else
ret = enumValue.ToString(Nothing)
End If
Else
ret = MyBase.ConvertTo(context, culture, value, destinationType)
End If
Return ret
End Function
End Class
<TypeConverter(GetType(EnumDescriptionConverter(Of Sandwiches)))>
Public Enum Sandwiches
<ComponentModel.Description("Ham Sandwich")> HamSandwich
<ComponentModel.Description("Reuben")> Reuben
<ComponentModel.Description("Po’ Boy")> PoBoy
<ComponentModel.Description("Grilled Cheese")> GrilledCheese
End Enum
ComboBox1.Items.AddRange(System.Enum.GetValues(GetType(Sandwiches)).Cast(Of Object).ToArray())