将枚举的所有描述绑定到组合框 [英] Bind all Descriptions of an enum to a combobox

查看:47
本文介绍了将枚举的所有描述绑定到组合框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将枚举的格式化字符串描述绑定到组合框?我希望组合框显示说明,而不是枚举.

我有一个这样的枚举:

 公共枚举三明治< ComponentModel.Description(火腿三明治")>火腿三明治< ComponentModel.Description(鲁本"))>鲁本< ComponentModel.Description("Po’Boy"))>PoBoy< ComponentModel.Description(烤奶酪")>烤奶酪结束枚举 

在描述字符串已绑定到组合框之后,我可以使用此功能将所选项目转换回枚举:

 公共函数GetEnumFromDescriptionAttribute(Of T)(描述为字符串)作为T昏暗的类型作为类型= GetType(T)如果不是type.IsEnum然后抛出新的InvalidOperationException()万一对于每个fi作为Reflection.FieldInfo in type.GetFields()昏暗的descriptionAttribute为ComponentModel.DescriptionAttribute = TryCast(Attribute.GetCustomAttribute(fi,GetType(ComponentModel.DescriptionAttribute)),ComponentModel.DescriptionAttribute)如果descriptionAttribute不算什么,则如果descriptionAttribute.Description<>然后描述继续万一返回DirectCast(fi.GetValue(Nothing),T)万一如果fi.Name<>然后描述继续万一返回DirectCast(fi.GetValue(Nothing),T)下一个一无所有结束功能 

但是我找不到一种将所有枚举绑定到组合框的干净方法.我知道,通常建议的解决方案是将枚举和枚举描述转换为字典,然后将其设置为cbo DisplayMember和ValueMember.但是我不知道该怎么做.

我已经就如何做到这一点完成了数十个局部解决方案.问题在于它们都是用C#编写的,在Option Strict关闭的情况下使用隐式转换,并且没有显示完整的实现.因此,对我来说,将任何解决方案都转换成.NET都是不可能的,因为我不知道将什么类型的变量定义为.

解决方案

看来您的目标是覆盖Enum值的字符串表示形式.基本表示形式显示Enum的名称,在此位置要显示Enum的Description属性.

假设这是WinForm的组合框,则标准方法是使用自定义

使用 ComboBox.SelectedItem 检索所选值.

How can I bind the formatted string descriptions of an enumeration to a combobox? I want the combobox to show the descriptions, not the enum.

I have an enum like this:

Public Enum Sandwiches
<ComponentModel.Description("Ham Sandwich")> HamSandwich
<ComponentModel.Description("Reuben")> Reuben
<ComponentModel.Description("Po’ Boy")> PoBoy
<ComponentModel.Description("Grilled Cheese")> GrilledCheese
End Enum

I can use this function to convert the selected item back to an enum, after the description string has already been bound to a combobox:

        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

But I cannot find a clean way to bind all of the enumerations to the combobox. I know that an often sugested solution is to convert the enums and enum descriptions to a dictionary, and then set those as the cbo DisplayMember and ValueMember. But I cannot figure out how to actually do that.,

I've ready through dozens of partial solutions on how to do this; The problem is that they are all written in C#, use implicit conversion with Option Strict turned OFF, and don't show the full implementation. So it's impossible for me to translate any of the solutions into .NET, since I have no idea what type variables have been defined as.

解决方案

It appears that your goal is override the string representation of a Enum value. The base representation displays Enum's name, where-as you want to display the Enum's Description attribute.

Assuming that this is a WinForm's combobox, the standard way would be to decorate the Enum with a custom TypeConverter and override the ConvertTo method. Using the EnumConverter Class and the basis for the custom converter minimizes the required code.

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

Modify your Enum definition to use this custom converter.

<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

Now all you need to do is load the ComboBox.Items with Enum values.

ComboBox1.Items.AddRange(System.Enum.GetValues(GetType(Sandwiches)).Cast(Of Object).ToArray())

Use the ComboBox.SelectedItem to retrieve the selected value.

这篇关于将枚举的所有描述绑定到组合框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆