Custom ComboBox


This is another forum request.  I’ve seen multiple requests from users who are looking to customize the drop down window for the ComboBox control.  There is no builtin way to do this with the existing control.  Instead you must create a custom solution.


Start by adding a new UserControl to your windows application or library project.  Have it inherit from ComboBox and call it CustomComboBox. 


This ComboBox will display a user provided control for the drop down window.  We will be using an instance of System.Windows.Form (named m_form) to replace the drop down window.  The idea is to have the control to essentially float below the ComboBox much like the drop down window does today.  To do this we need to custom the Form to not show up in the task bar and to not have a titlebar or default buttons.


We also need to prevent the ComboBox from droping down the builtin window. There is no way to actually stop the ComboBox from dropping down the window. Instead we need to make it appear that the drop down didn’t display by setting it’s height to 1 pixel.


To make the logic a bit easier, we will also provide a default empty control to be displayed when the drop down is expanded


Here is the full text of the constructor used to initialize the CustomComboBox

Public Sub New()

‘ This call is required by the Windows Form Designer.
InitializeComponent()

‘ Setup the form to display the control
m_form = New Form()
m_form.StartPosition = FormStartPosition.Manual
m_form.FormBorderStyle = FormBorderStyle.None
m_form.Hide()
m_form.ShowInTaskbar = False

Me.Control = New Control() ‘ Default Control
m_dropDownHeight = Me.DropDownHeight
Me.DropDownHeight = 1 ‘ Prevent the DropDown from showing
End Sub


The next step is to have the form display in the proper place when the drop down button is hit. To do this we override the OnDropDown() method and add the display logic there.

    Protected Overrides Sub OnDropDown(ByVal e As System.EventArgs)
MyBase.OnDropDown(e)

If Not m_form.Visible Then
DisplayControl()
End If

Me.DroppedDown = False
End Sub

Private Sub DisplayControl()
Dim loc As Point = Me.PointToScreen(Point.Empty)
loc.Y += Me.Height

m_form.Location = loc
m_form.Show()
End Sub


The last item left is to add a property for the user to set the custom control to display. To be flexible we will allow instances of Control. It will be docked in the form. We also need to listen to the LostFocus event on the control. This is the key for us to hide the form like when the user clicks away from the normal ComboBox.

   Public Property Control() As Control
Get
Return m_control
End Get
Set(ByVal value As Control)
If Not m_control Is Nothing Then
m_form.Controls.Remove(m_control)
RemoveHandler m_control.LostFocus, AddressOf Me.OnControlLostFocus
End If

m_control = value
m_control.Dock = DockStyle.Fill
AddHandler m_control.LostFocus, AddressOf Me.OnControlLostFocus
m_form.Controls.Add(m_control)
End Set
End Property

Private Sub OnControlLostFocus(ByVal sender As Object, ByVal e As EventArgs)
m_form.Hide()
End Sub


Comments (2)

  1. Do you have a sample for using this in VB.NET? I cannot get it to work..

  2. jaredpar says:

    Sure.  Here’s one of the test forms I used to verify that the CustomComboBox will display correctly.  I created a basic windows form and dropped an instance of CustomComboBox onto it and went from there.

    Public Class CustomComboForm

       Sub New()

           ‘ This call is required by the Windows Form Designer.

           InitializeComponent()

           ‘ Add any initialization after the InitializeComponent() call.

           Dim tv As New TreeView()

           tv.Nodes.Add("foo")

           tv.Nodes.Add("bar").Nodes.Add("child")

           CustomComboBox1.Control = tv

       End Sub

    End Class