• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 581
  • Last Modified:

How to have more than 1 column in a combobox and populate values to multicolumns

I want to have a combobox which should populate Customer Name, CustomerID and DateOfBirth.
Therefore, my combobox should have three columns and the values for each columns should be filled after running a sqlreader.
Thanks
0
JOLEEJJ
Asked:
JOLEEJJ
  • 4
  • 4
1 Solution
 
Slow_moCommented:
You will have to use a custom combobox control, as a standard one does not allow to have more than one column.
Try if this works: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=140260&SiteID=1
0
 
JOLEEJJAuthor Commented:
Hi
After creating the usercontrol using the code in the above link,  I have the following error.  I believe this code was written for vb.net 2003 but I need it for vb.net 2005.

Imports System.Windows
 
Public Class MultiColumnCombo
 
    Inherits System.Windows.Forms.ComboBox
 
    Private _ColumnWidths As String = "100"
 
    Private _ColumnWidthsArray As String()
 
    Private _DoNotReact As Boolean = False
 
    Private _Textchanged As Boolean = False
 
    Sub New()
 
        MyBase.New()
 
        MyBase.DrawMode = Forms.DrawMode.OwnerDrawFixed
 
        'SetStyle(ControlStyles.UserPaint, True)
 
        'SetStyle(ControlStyles.AllPaintingInWmPaint, True)
 
        'SetStyle(ControlStyles.DoubleBuffer, True)
 
    End Sub
 
 
 
 
 
    Public Property ColumnWidths() As String
 
        Get
 
            Return _ColumnWidths
 
        End Get
 
        Set(ByVal Value As String)
 
            _ColumnWidths = Value
 
            _ColumnWidthsArray = Value.Split(CType(";", Char))
 
            Dim w As Integer = 0
 
            For Each str As String In _ColumnWidthsArray
 
                w += CInt(str)
 
            Next str
 
            MyBase.DropDownWidth = w + 10
 
        End Set
 
    End Property
 
 
 
    Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
 
        ' Set the DrawMode property to draw fixed sized items.
 
 
 
        ' 
 
        'If _Textchanged Then
 
        '    _Textchanged = False
 
        '    Exit Sub
 
        'End If
 
 
 
        Dim myBrush As Brush
 
        'If e.Bounds.Y = 0 Then
 
        '    ItemHeight = 32
 
        'Else
 
        '    ItemHeight = 16
 
        'End If
 
        '  e.DrawBackground()
 
        Dim LightColor As Color = Color.Blue
 
        Dim DarkColor As Color = Color.Black
 
        Dim GradBrush As Brush = New Drawing2D.LinearGradientBrush(e.Bounds, LightColor, DarkColor, Drawing2D.LinearGradientMode.Vertical)
 
 
 
 
 
 
 
        Select Case CInt((e.State And DrawItemState.Selected))
 
            'Case DrawItemState.Selected + DrawItemState.NoAccelerator + DrawItemState.NoFocusRect, DrawItemState.Selected
 
            Case DrawItemState.Selected
 
                myBrush = New SolidBrush(BackColor)
 
                e.Graphics.FillRectangle(GradBrush, e.Bounds)
 
            Case Else
 
                myBrush = New SolidBrush(ForeColor)
 
                'myBrush = GradBrush
 
                e.Graphics.FillRectangle(New SolidBrush(BackColor), e.Bounds)
 
        End Select
 
 
 
 
 
 
 
        Dim str As String
 
        ' Draw the current item text based on the current Font and the custom brush settings.
 
        Dim row As DataRowView = (CType(MyBase.Items(e.Index), DataRowView))
 
        Dim newpos As Integer = e.Bounds.X
 
        Dim endpos As Integer = e.Bounds.X
 
 
 
        For indx As Integer = 0 To UBound(_ColumnWidthsArray)
 
            Dim ColLength As Integer = CType(_ColumnWidthsArray(indx), Integer)
 
            endpos += ColLength
 
 
 
            Dim Charaant As Integer = CInt(Math.Round(CDbl(ColLength) / 6.2))
 
            Dim rawitem As String = row.Item(indx).ToString()
 
 
 
            If ColLength <> 0 Then
 
 
 
 
 
                If Charaant > rawitem.Length Then
 
                    str = rawitem
 
 
 
                Else
 
 
 
                    str = rawitem.Substring(0, Charaant)
 
                End If
 
 
 
                Dim r As RectangleF = New RectangleF(newpos + 2, e.Bounds.Y, endpos - 1, e.Bounds.Height)
 
 
 
                'e.Graphics.FillRectangle(myBrush, r)
 
 
 
                e.Graphics.DrawString(str, e.Font, myBrush, r)
 
 
 
                'ControlPaint.DrawBorder3D(e.Graphics, New Rectangle(endpos + 2, e.Bounds.Y, newpos, e.Bounds.Height))
 
                'e.Graphics.DrawString("mycol", e.Font, myBrush, New RectangleF(newpos, 0, CInt(_ColumnWidthsArray(indx)), ItemHeight))
 
                If indx <= UBound(_ColumnWidthsArray) Then
 
                    e.Graphics.DrawLine(New Pen(Color.Black), endpos, e.Bounds.Y, endpos, Me.ItemHeight * Me.MaxDropDownItems)
 
                    e.Graphics.DrawLine(New Pen(Color.LightGray), endpos + 1, e.Bounds.Y, endpos + 1, Me.ItemHeight * Me.MaxDropDownItems)
 
                End If
 
            End If
 
 
 
            newpos = endpos
 
        Next
 
        '        e.DrawFocusRectangle()
 
        myBrush.Dispose()
 
        GradBrush.Dispose()
 
 
 
 
 
    End Sub
 
 
 
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
 
 
 
        Dim foundIndex As Integer, textlngth As Integer
 
        If _DoNotReact = False Then
 
            If Me.AccessibilityObject.Value Is Nothing Then
 
                textlngth = 0
 
                Exit Sub
 
            Else
 
                textlngth = Me.AccessibilityObject.Value.Length
 
            End If
 
 
 
            If textlngth = 0 Then
 
                MyBase.OnTextChanged(e)
 
                _DoNotReact = False
 
                _Textchanged = False
 
                Exit Sub
 
            End If
 
 
 
            If textlngth <> 0 Then
 
 
 
                _DoNotReact = True
 
                foundIndex = FindString(Me.AccessibilityObject.Value)
 
                If foundIndex > -1 Then
 
                    Me.SelectedIndex = foundIndex
 
                    Me.Select(textlngth, Me.Text.Length - textlngth)
 
                    'Me.SelectionStart = textlngth
 
                    _Textchanged = True
 
                Else
 
                    _Textchanged = False
 
                End If
 
                _DoNotReact = False
 
            End If
 
            MyBase.OnTextChanged(e)
 
        End If
 
        _DoNotReact = False
 
 
 
 
 
 
 
    End Sub
 
 
 
    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
 
        Select Case e.KeyCode
 
            Case Keys.Back, Keys.Enter, Keys.Delete
 
                _DoNotReact = True
 
            Case Keys.Down
 
                Me.DroppedDown = True
 
                Invalidate()
 
 
 
        End Select
 
 
 
        MyBase.OnKeyDown(e)
 
 
 
    End Sub
 
 
 
    Protected Overrides Sub Finalize()
        MyBase.Finalize()
    End Sub
End Class

Open in new window

0
 
Slow_moCommented:
This works on VB.2005
You must add an Accessibility reference to project
Imports System.Windows
 
Public Class MultiColumnCombo
 
    Inherits System.Windows.Forms.ComboBox
 
    Private _ColumnWidths As String = "100"
 
    Private _ColumnWidthsArray As String()
 
    Private _DoNotReact As Boolean = False
 
    Private _Textchanged As Boolean = False
 
    Sub New()
 
        MyBase.New()
 
        MyBase.DrawMode = Forms.DrawMode.OwnerDrawFixed
 
        'SetStyle(ControlStyles.UserPaint, True)
 
        'SetStyle(ControlStyles.AllPaintingInWmPaint, True)
 
        'SetStyle(ControlStyles.DoubleBuffer, True)
 
    End Sub
 
 
    Public Property ColumnWidths() As String
 
        Get
 
            Return _ColumnWidths
 
        End Get
 
        Set(ByVal Value As String)
 
            _ColumnWidths = Value
 
            _ColumnWidthsArray = Value.Split(CType(";", Char))
 
            Dim w As Integer = 0
 
            For Each str As String In _ColumnWidthsArray
 
                w += CInt(str)
 
            Next str
 
            MyBase.DropDownWidth = w + 10
 
        End Set
 
    End Property
 
 
 
    Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
 
        ' Set the DrawMode property to draw fixed sized items.
 
 
 
        ' 
 
        'If _Textchanged Then
 
        '    _Textchanged = False
 
        '    Exit Sub
 
        'End If
 
 
 
        Dim myBrush As Brush
 
        'If e.Bounds.Y = 0 Then
 
        '    ItemHeight = 32
 
        'Else
 
        '    ItemHeight = 16
 
        'End If
 
        '  e.DrawBackground()
 
        Dim LightColor As Color = Color.Blue
 
        Dim DarkColor As Color = Color.Black
 
        Dim GradBrush As Brush = New Drawing2D.LinearGradientBrush(e.Bounds, LightColor, DarkColor, Drawing2D.LinearGradientMode.Vertical)
 
 
        Select Case CInt((e.State And DrawItemState.Selected))
 
            'Case DrawItemState.Selected + DrawItemState.NoAccelerator + DrawItemState.NoFocusRect, DrawItemState.Selected
 
            Case DrawItemState.Selected
 
                myBrush = New SolidBrush(BackColor)
 
                e.Graphics.FillRectangle(GradBrush, e.Bounds)
 
            Case Else
 
                myBrush = New SolidBrush(ForeColor)
 
                'myBrush = GradBrush
 
                e.Graphics.FillRectangle(New SolidBrush(BackColor), e.Bounds)
 
        End Select
 
 
        Dim str As String
 
        ' Draw the current item text based on the current Font and the custom brush settings.
 
        Dim row As DataRowView = (CType(MyBase.Items(e.Index), DataRowView))
 
        Dim newpos As Integer = e.Bounds.X
 
        Dim endpos As Integer = e.Bounds.X
 
 
 
        For indx As Integer = 0 To UBound(_ColumnWidthsArray)
 
            Dim ColLength As Integer = CType(_ColumnWidthsArray(indx), Integer)
 
            endpos += ColLength
 
 
 
            Dim Charaant As Integer = CInt(Math.Round(CDbl(ColLength) / 6.2))
 
            Dim rawitem As String = row.Item(indx).ToString()
 
 
 
            If ColLength <> 0 Then
 
 
 
 
 
                If Charaant > rawitem.Length Then
 
                    str = rawitem
 
 
 
                Else
 
 
 
                    str = rawitem.Substring(0, Charaant)
 
                End If
 
 
 
                Dim r As RectangleF = New RectangleF(newpos + 2, e.Bounds.Y, endpos - 1, e.Bounds.Height)
 
 
 
                'e.Graphics.FillRectangle(myBrush, r)
 
 
 
                e.Graphics.DrawString(str, e.Font, myBrush, r)
 
 
 
                'ControlPaint.DrawBorder3D(e.Graphics, New Rectangle(endpos + 2, e.Bounds.Y, newpos, e.Bounds.Height))
 
                'e.Graphics.DrawString("mycol", e.Font, myBrush, New RectangleF(newpos, 0, CInt(_ColumnWidthsArray(indx)), ItemHeight))
 
                If indx <= UBound(_ColumnWidthsArray) Then
 
                    e.Graphics.DrawLine(New Pen(Color.Black), endpos, e.Bounds.Y, endpos, Me.ItemHeight * Me.MaxDropDownItems)
 
                    e.Graphics.DrawLine(New Pen(Color.LightGray), endpos + 1, e.Bounds.Y, endpos + 1, Me.ItemHeight * Me.MaxDropDownItems)
 
                End If
 
            End If
 
 
 
            newpos = endpos
 
        Next
 
        '        e.DrawFocusRectangle()
 
        myBrush.Dispose()
 
        GradBrush.Dispose()
 
    End Sub
 
 
 
    Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
 
 
 
        Dim foundIndex As Integer, textlngth As Integer
 
        If _DoNotReact = False Then
 
            If Me.AccessibilityObject.Value Is Nothing Then
 
                textlngth = 0
 
                Exit Sub
 
            Else
 
                textlngth = Me.AccessibilityObject.Value.Length
 
            End If
 
 
 
            If textlngth = 0 Then
 
                MyBase.OnTextChanged(e)
 
                _DoNotReact = False
 
                _Textchanged = False
 
                Exit Sub
 
            End If
 
 
 
            If textlngth <> 0 Then
 
 
 
                _DoNotReact = True
 
                foundIndex = FindString(Me.AccessibilityObject.Value)
 
                If foundIndex > -1 Then
 
                    Me.SelectedIndex = foundIndex
 
                    Me.Select(textlngth, Me.Text.Length - textlngth)
 
                    'Me.SelectionStart = textlngth
 
                    _Textchanged = True
 
                Else
 
                    _Textchanged = False
 
                End If
 
                _DoNotReact = False
 
            End If
 
            MyBase.OnTextChanged(e)
 
        End If
 
        _DoNotReact = False
 
 
    End Sub
 
 
 
    Protected Overrides Sub OnKeyDown(ByVal e As System.Windows.Forms.KeyEventArgs)
 
        Select Case e.KeyCode
 
            Case Keys.Back, Keys.Enter, Keys.Delete
 
                _DoNotReact = True
 
            Case Keys.Down
 
                Me.DroppedDown = True
 
                Invalidate()
 
 
 
        End Select
        MyBase.OnKeyDown(e)
    End Sub
 
 
 
    Protected Overrides Sub Finalize()
        MyBase.Finalize()
    End Sub
End Class

Open in new window

0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
JOLEEJJAuthor Commented:
Hi
Now the multicolumcombobox is created in my form but when you add values to the columns, it generates the following error message.

"Unable to cast object of type 'System.String' to type 'System.Data.DataRowView'."

under code:

Dim row As DataRowView = (CType(MyBase.Items(e.Index), DataRowView))

Can you please check this to fix this problem?

Thanks
0
 
Slow_moCommented:
That's because this control must be assigned a DataSource which is a table. I tried that and to be honest, did not quite like the control.

Maybe try this one. It comes with example:
http://www.codeproject.com/KB/cpp/multicolumncombo.aspx
0
 
JOLEEJJAuthor Commented:
Hi
After downloading the zip file, I convert the project into vb.2005 and then when I tried to run the project, it generated the following error message:

"A Project with out Output Type of Class Library can not be started directly.
In order to debug this project, add an executable project to this solution which
references  the library project.  Set the executable project as the startup project."

I don't know how to fix it...!!!
0
 
JOLEEJJAuthor Commented:
Hi
Is anybody there to fix this problem?
Thanks
0
 
Slow_moCommented:
The solution contains two separate projects. The first one is user control that can not be run separately. The second is a project that references mentioned user control. In solution explorer right click the second one (CodeSampleTest), and set it as startup project.
Now you should be able to test the code.
0

Featured Post

The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now