Post

WinForms ComboBox -> DevExpress ComboBoxEdit (migration)

I found a couple of solutions on the DevExpress website for how to use the ComboBoxEdit component the way I wanted, however, none of them seemed to provide a smooth transition from the WinForms databound combo box to the DevExpress counterpart. So using some fo the examples that I found, reading through the help and reflecting on the subject for a whole five minutes… here is what I ended up with.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
Option Explicit On
Option Strict On
Option Infer On
 
Imports System.ComponentModel
 
<ProvideProperty("DisplayMember", GetType(Control))> _
<ProvideProperty("ValueMember", GetType(Control))> _
<ProvideProperty("DataSource", GetType(Control))> _
Public Class ComboBoxEditEx
  Inherits DevExpress.XtraEditors.ComboBoxEdit
 
  Private m_valueMember As String
  Private m_displayMember As String
 
  <Category("Data")> _
  <Description("Indicate the property to display for the items in this control.")> _
  Public Property DisplayMember() As String
    Get
      Return m_displayMember
    End Get
    Set(ByVal value As String)
      m_displayMember = value
    End Set
  End Property
 
  <Category("Data")> _
  <Description("Indicates the property to use as the actual value for the items in the control.")> 
  Public Property ValueMember() As String
    Get
      Return m_valueMember
    End Get
    Set(ByVal value As String)
      m_valueMember = value
    End Set
  End Property
  
  <Category("Data")> _
  <Description("Indicates the list that this control will use to get its items.")> _
  Public WriteOnly Property DataSource() As DataTable
    Set(ByVal value As DataTable)
      Dim item As New ComboItem(Me.ValueMember, Me.DisplayMember)
      item.SetDataSource(Me, value)
    End Set
  End Property
  
  <Browsable(False)> _
  Public Property SelectedValue() As Object
    Get
      Dim item As New ComboItem(ValueMember, DisplayMember)
      Return item.GetItemValue(Me)
    End Get
    Set(ByVal value As Object)
      Dim item As New ComboItem(Me.ValueMember, Me.DisplayMember)
      item.SelectItem(Me, value)
    End Set
  End Property
  
  <Browsable(False)> _
  Public ReadOnly Property Items() As DevExpress.XtraEditors.Controls.ComboBoxItemCollection
    Get
      Return Me.Properties.Items
    End Get
  End Property
  
End Class

Friend Class ComboItem
  
  Private m_value As Object
  Private m_displayText As String
  
  Friend Sub New(ByVal valueMember As Object, ByVal displayMember As String)
    m_value = valueMember
    m_displayText = displayMember
  End Sub
  
  Public Overrides Function ToString() As String
    Return m_displayText
  End Function
  
  Friend ReadOnly Property Value() As Object
    Get
      Return m_value
    End Get
  End Property
  
  Friend Sub SetDataSource(ByRef control As ComboBoxEditEx, ByVal dt As DataTable)
    For Each row As DataRow In dt.Rows
      Dim item As ComboItem = New ComboItem(row.Item(control.ValueMember), CStr(row.Item(control.DisplayMember)))
      control.Properties.Items.Add(item)
    Next
  End Sub
  
  Friend Function GetItemValue(ByRef control As ComboBoxEditEx) As Object
    Dim item As ComboItem = TryCast(control.SelectedItem, ComboItem)
    If item Is Nothing Then
      Return Nothing
    Else
      Return item.Value
    End If
  End Function
  
  Friend Sub SelectItem(ByRef control As ComboBoxEditEx, ByVal value As Object)
  
    Dim index As Integer = 0
  
    For Each obj As Object In control.Properties.Items
      Dim item As ComboItem = TryCast(obj, ComboItem)
      If item IsNot Nothing AndAlso _
          item.Value.Equals(value) Then
        Exit For
      Else
        index += 1
      End If
    Next
  
    If index >= control.Properties.Items.Count Then
      control.SelectedIndex = -1
    Else
      control.SelectedIndex = index
    End If
 
  End Sub

End Class

The overall goal was to provide a seamless transition (read: drop in replacement) for the combo boxes I already had on existing forms to migrate to use all DevExpress controls since I wanted to take advantage of the skinning tech in XtraForm. So what I needed was an easy way to take the existing data tables I had bound to WinForms combo boxes, the code already used to assign (SelectedValue and SelectedIndex depending on circumstances). So far this has worked out pretty nicely. If you are in the same situation… here you go…

This post is licensed under CC BY 4.0 by the author.