0 Replies - 1110 Views - Last Post: 15 February 2016 - 01:55 PM

#1 maceysoftware  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 350
  • View blog
  • Posts: 1,508
  • Joined: 07-September 13

Databinding an Enum to a Combobox

Posted 15 February 2016 - 01:55 PM

What I have been finding lately is that enum’s are great however in their raw state they can’t do a lot and you end up duplicating a description or values along the way. Especially in for settings, for example you may have a setting on your application to say what happens when you close your application, it could shut down, minimise or close to the icon tray.
That’s three options but the user can only choose one, now choosing the right control to display that is easy, its either radio buttons or a ComboBox, but then who uses radio buttons these days? Sure they are fine but why take up that much room when you could just have a ComboBox. So that’s the control decided.
Now you’re going to have code in somewhere what each value means, you could do this in a system table in a database(if you have one, maybe your application doesn’t) and bring back the list and databind to the table… or you could create a enum and bind the enum directly to the ComboBox.
This is the way this snippet will show you. This is only a little portion of what this code can do, you can twink this code slightly and get it working for DataGridViewComboBoxColumns as well.

Ok so here is my example of an Enum, getting names hey?
Public Enum ExampleEnum
    <Description("The Foo")>
    Foo = 0
    <Description("Bar")>
    Bar
    <Description("Baz")>
    Baz
    <Description("Qux")>
    Qux
End Enum

Ok so it is nice and simple, it is just using the standard placeholder’s names, oh and that <Description> part is just an attribute, if you import ‘System.ComponentModel’ you will be able to use it. Now the description you place on these enum’s is actually the description which will be shown in the combobox.
Now the second part can be done in two ways.
The first is creating a class called myComboBox or whatever you want to call it, and inheriting system.windows.forms.combobox, as shown below:

Public Class MyComboBox
    Inherits ComboBox

    Public Sub BindFromEnum(t As Type)

        Dim bindingPair As New List(Of KeyValuePair)

        ' loop through each fieldInfo within the type using reflection (Import System.Reflection), however skip the first one, i found this was giving duff information
        For Each fInfo As FieldInfo In t.GetFields.Skip(1)
            ' Again using reflection get the description on the field, this will allow us to use the description mentioned earlier form each of the enum values.
            Dim attributes As DescriptionAttribute() = DirectCast(fInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

            ' now if we successfully find a description Attribute then we can add this value and description to our list to bind
            If attributes IsNot Nothing AndAlso attributes.Length > 0 Then
                bindingPair.Add(New KeyValuePair(CInt(fInfo.GetRawConstantValue), attributes(0).Description))
            Else
                ' if we can't we will just take the name of the field, which for our standard fields this is not a problem, 
                'the description side really comes in handy if you want to give something a friendly name For example:
                'Private Enum ClosingActions
                '    CloseToTray = 0
                '    Close
                '    Minimise
                'End Enum
                ' you see in the enum above you would want to give CloseToTray a friendly name as you wouldn't want the user confronted with "CloseToTray" in a combobox.
                bindingPair.Add(New KeyValuePair(CInt(fInfo.GetRawConstantValue), fInfo.Name))
            End If
        Next

        DataSource = bindingPair
        DisplayMember = "Description"
        ValueMember = "Id"

    End Sub

‘ private class which is only used to store the data to databind
    Private Class KeyValuePair

        Property Id As Integer
        Property Description As String

        Sub New(id As Integer, description As String)
            Me.Id = id
            Me.Description = description
        End Sub

    End Class

End Class 

The other way in which this can be completed and a way I don’t see discussed in the VB.Net forums often is with the use of Extension Methods.

Extensions methods is a really easy way in which you can add functionality into controls without having to completely inherit a control.

Extension method I believe have to be created in a module, using the same code as before but this time in a extension method:

Public Module ExtensionMethods

    <Runtime.CompilerServices.Extension>
    Public Sub BindFromEnum(Combo As ComboBox, t As Type)

        Dim bindingPair As New List(Of KeyValuePair)

        ' loop through each fieldInfo within the type using reflection (Import System.Reflection), however skip the first one, i found this was giving duff information
        For Each fInfo As FieldInfo In t.GetFields.Skip(1)
            ' Again using reflection get the description on the field, this will allow us to use the description mentioned earlier form each of the enum values.
            Dim attributes As DescriptionAttribute() = DirectCast(fInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())

            ' now if we successfully find a description Attribute then we can add this value and description to our list to bind
            If attributes IsNot Nothing AndAlso attributes.Length > 0 Then
                bindingPair.Add(New KeyValuePair(CInt(fInfo.GetRawConstantValue), attributes(0).Description))
            Else
                ' if we can't we will just take the name of the field, which for our standard fields this is not a problem, 
                'the description side really comes in handy if you want to give something a friendly name For example:
                'Private Enum ClosingActions
                '    CloseToTray = 0
                '    Close
                '    Minimise
                'End Enum
                ' you see in the enum above you would want to give CloseToTray a friendly name as you wouldn't want the user confronted with "CloseToTray" in a combobox.
                bindingPair.Add(New KeyValuePair(CInt(fInfo.GetRawConstantValue), fInfo.Name))
            End If
        Next

        ' Finish off by binding the list to the combobox
        Combo.DataSource = bindingPair
        Combo.DisplayMember = "Description"
        Combo.ValueMember = "Id"

    End Sub

    Private Class KeyValuePair

        Property Id As Integer
        Property Description As String

        Sub New()
            Id = -1
        End Sub

        Sub New(id As Integer, description As String)
            Me.Id = id
            Me.Description = description
        End Sub


    End Class

End Module


You can see this time the first parameter being passed into the extension method is the ComboBox, now don’t let this put you off you don’t have to pass this through, it uses this parameter to work out which control you want this extension method on, the method will also pass through the control, using this parameter so you can use it in part of your code, just like I am when I am setting the datasource.
Both ways will then allow you to bind a Enum to a datagridview using the following code:
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ComboBox1.BindFromEnum(GetType(ExampleEnum))
        MyComboBox1.BindFromEnum(GetType(ExampleEnum))
    End Sub


Is This A Good Question/Topic? 0
  • +

Page 1 of 1