Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

MCCB - Multi Column ComboBox - How to create a simple (UserControl) DLL

4.70/5 (14 votes)
9 Mar 2016CPOL12 min read 23.7K   1.4K  
Remembering the first time, being already an experienced programmer in VB and VBA, I felt the need to build my first reusable DLL.

Image 1

Image 2

First of all

CodeProject is for programmers of all levels. This article is intended only for beginners and VB programmers who have never built a DLL. For a more complex ComboBox, see my first article: ExCB - Extended Multi Column ComboBox

Introduction

The downloadable files contain complete projects, but I'll show the basic steps in creating this Control, one ComboBox able to permanently display one or more Columns (say 'field boxes', labeled or not) and a List for 'record' selection.

A DLL is often a Control, made up with other System.Windows.Form Controls, created by the user for a particular purpose, often flexible, parametrizable, and ready to execute several tasks.

Like any other Control, a UserControl has its own Properties, Methods and Events, some of them created by us.

When developing a DLL, it's good practice to have another simple WinForms project for testing the Control, both projects in a Solution, so we can deeply test and debug the Control's behavior.

Building the UserControl

  1. Open Visual Studio, Start a New Project, choose Class Library and give it the Name MCCB, which will be the Project name, the Assembly name and the Root namespace - but VS gives you a VB Public Class Class1
  2. Menu PROJECT, choose Add User Control and give it the Name MCCB, which will be the future Name of your Control - VS creates another Class and shows the template - a 150x150 square, more like a Panel than like a Form...

In this example, the goal is to create a ComboBox that expose permanently one or more columns, with labels. We create the first column, all others will be created at runtime. We also need a drop-down List and a Button for opening the List.

  1. Resize the Control to appx. 200x200 and change its BackColor to any other (slight). At runtime, this color will be changed to Color.Control, but at design time we need a visual reference, when resizing the Control.
  2. Lets start with the Label (Title/Header): Pick a Label from the Toolbox. Change the following properties: Name="Hdr0", AutoSize=False, BackColor=WhiteSmoke, BorderStyle=FixedSingle, Location=0;0, Size=100;19, Text="Hdr0", TextAlign=MiddleLeft
  3. Now the Box to show the field value. Instead of a TextBox, we'll use a Label... is a lighter control, furthermore, values are not to be written or changed. Pick another Label and change the following properties: Name="Box0", AutoSize=False, BackColor=White, BorderStyle=FixedSingle, ForeColor=Navy, Location=0;18, Size=100;20, Text="Box0", TextAlign=MiddleLeft
  4. Next, the List. Pick a ListView and change the properties: Name="MyLV", View=Details, BorderStyle=FixedSingle, FullRowSelect=True, GridLines=True, HeaderStyle=None, Location=0;37, MultiSelect=False, Size=119;138. Its a List with 8 Rows, without Header ... We'll also create the first Column: Add a Column and change the properties: Name="lvCol0", Text="", Width=97. Why 97? To perfectly align the lines, the ListView Column's Width must be the Width of the corresponding Label/Box minus 1, except the first Column, which must be minus 3...
  5. Finally, the Button, which must show any kind of "down arrow". It can be a Button, a PictureBox, even a simple Label. Lets do it with a Label. Pick a Label and change properties: Name="LblDrop", AutoSize=False, BackColor=WhiteSmoke, BorderStyle=FixedSingle, Location=99;18, Size=20;20, Text="". In property Image - Local resource - Import: DArrow.png, located in folder .\Image

Image 3

  1. Everything is OK and aligned, right? But when the Control is to be placed on a Form, the List must be hidden... So, to prevent vertical resizing at design time, and because the actual height of Header+Box is 38, add this very first code, in the UserControl's Resize Event:
VB
Private Sub MCCB_Resize(sender As Object, e As EventArgs) Handles Me.Resize
	Me.Height = 38
End Sub
  1. Its time to create the project for testing and debugging the Control. Save the Project and start a New Project of the type Windows Forms Application, naming it as MCCB_Test - VS gives you a Form template (Form1). Save this 2nd project.
  2. Add the UserControl project: Menu FILE - Add - Existing Project - Browse MCCB project and open MCCB.vbproj - A Solution 'MCCB_Test' is created, with both projects in Solution Explorer. Select MCCB project, Menu BUILD - Build MCCB. Open the Toolbox and look at the top ... The Control MCCB is already there. Double-click it - the Control is placed in the Form, with the Name Mccb1. Resize it - as you can see, only horizontal resizing is allowed. Start the Solution - Great, the Control is there!!! Now you can manage both projects. Insert a piece of code, Menu BUILD - Rebuild MCCB, if necessary check or change Control Properties in Form1, define breakpoint(s) for Debug porposes, if needed, and Start the Solution. Easy.

We're about to create a set of Properties. Usually, Properties must be Public and specify its Data Type. Custom Properties values can be viewed and changed, like any other Property in the IDE Properties Window, or at runtime. All of our Properties, except one, are likely to be read and altered in the IDE Properties Window. Some of them will alter the Control's appearance: Height of Header(s) and Box(es), BorderStyle, ForeColor and BackColor of Header(s), Box(es) and List. These Properties imply the Control to be redrawn, we'll see later. They have their defined Data Types - Integer, Byte, Color, BorderStyle - which can be changed with pre-defined Dialogs, ComboBoxes or TextBoxes. But, although the properties ListFontStyle and LayerOrder deal with Byte values, instead of a simple TextBox for typing a digit, we prefer a ComboBox with descriptive text for the allowed values. For that, we have to declare Data Types of our Enumeration lists. Finally, property SelectedIndex is to be used only at runtime, i.e., must be non-browsable and hidden. See all Properties here

  1. Select and Open MCCB.vb Code tab. Lets Import a reference, needed to specify some Properties Attributes, like Category, Description, Browsable or DesignerSerializationVisibility, and declare two Enum types and a couple of Variables - some for Property values (the _Name of the variable is the Name of the Property, preceded by an underscore), some for internal use:
VB
Imports System.ComponentModel   ' For PropertyAttributes

Public Class MCCB

VB
 Public Enum LFStyle         ' for Property ListFontStyle
      SameAsControl = 0
      AlwaysRegular = 1
End Enum
VB
 Public Enum LayOrder        ' for Property LayerOrder
     Normal = 0
     BringToFront = 1
     SendToBack = 2
End Enum
VB
' Property variables
Private _MaxItemsDisp As Integer = 8
Private _HeaderHeight As Byte = 19
Private _HeaderBackColor As Color = Color.WhiteSmoke
Private _HeaderForeColor As Color = Color.Black
Private _HeaderBorderStyle As BorderStyle = Windows.Forms.BorderStyle.FixedSingle
Private _BoxHeight As Byte = 20
Private _BoxBackColor As Color = Color.White
Private _BoxForeColor As Color = Color.MediumBlue
Private _BoxBorderStyle As BorderStyle = Windows.Forms.BorderStyle.FixedSingle
Private _ListBackColor As Color = Color.White
Private _ListForeColor As Color = Color.Black
Private _ListBorderStyle As BorderStyle = Windows.Forms.BorderStyle.FixedSingle
Private _ListFontStyle As Byte = 0      ' 0-SameAsControl, 1-AlwaysRegular
Private _LayerOrder As Byte = 0         ' 0-Normal, 1-BringToFront, 2-SendToBack
Private _SelectedIndex As Integer = -1
' Internal variables
Private _ColumnCount As Integer = 0
Private _ColumnIndex As Integer = 0
Private _TotalWidth As Integer = 99
Private _LeftLocation As Integer = 0
Private _ItemsCount As Integer = 0
Private _Me_MinHeight As Integer = _HeaderHeight + _BoxHeight - 1
Private _ListHeight As Integer = 0
Private _ShowList As Boolean = False    ' used in Resize event
Private _FNIlastIdx As Integer = -1     ' Last ColumnIndex searched
Private _FNIlastStr As String = ""      ' Last String searched
Private _FNI_iFrom As Integer = -1
Private _Error As String = "Error"
  1. As said before, most Properties imply the Control to be redrawn. And redraw the Control implies the Resize Event to be raised. Resize Event will be also called whenever the List is dropped down or hidden, i.e., when the 'button' LblDrop is clicked. So, Resize Event must deal with two different situations: 1) The List is to be dropped down (if there are Items to show), with its correct Height. 2) The list is to be hidden. And for controlling its behavior, we created a variable _ShowList, whose initial value is False, thus ensuring the correct scaling in design mode. So, let's change the UserControl's Resize Event. Note that _Me_MinHeight = _HeaderHeight + _BoxHeight - 1, so _Me_MinHeight represents always the (minimum) height of the Control, without List, and the height of the List is the number of rows to display, each one 17 pixels [16 (row height) + 1 (separator line)] plus 1 (last line):
VB
Private Sub MCCB_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    'Me.Height = 38     ' Replaced by the code below:
    If _ShowList And _ItemsCount > 0 Then
        _ListHeight = Math.Min(_ItemsCount, _MaxItemsDisp) * 17 + 1
    Else
        _ListHeight = 0
    End If
    Me.Height = _Me_MinHeight + _ListHeight
    MyLV.Height = _ListHeight
End Sub
  1. Resize Event is to be called (also) from several other situations, but the variable _ShowList must be set to the desired value. So, let's create a unique Sub that sets the value of the variable and invokes the Resize Event, which will be called in each of these situations:
VB
Private Sub ShowHideList(Show As Boolean)
    _ShowList = Show
    MCCB_Resize(Nothing, Nothing)
End Sub
  1. Now, lets provide a mechanism to Drop-down or Hide the List, when the label LblDrop is Clicked. And more, when the Mouse passes over the label, it's BackColor becomes Orange and the Cursor changes to Hand. So, let's use the Events MouseHover, MouseLeave and Click:
VB
Private Sub LblDrop_MouseHover(sender As Object, e As EventArgs) Handles LblDrop.MouseHover
    Me.Cursor = Cursors.Hand
    sender.BackColor = Color.Orange
End Sub
VB
Private Sub LblDrop_MouseLeave(sender As Object, e As EventArgs) Handles LblDrop.MouseLeave
    Me.Cursor = Cursors.Default
    sender.BackColor = Color.WhiteSmoke
End Sub
VB
Private Sub LblDrop_Click(sender As Object, e As EventArgs) Handles LblDrop.Click
    ShowHideList(Show:=(Me.Height <= _Me_MinHeight))
End Sub
  1. It's time to create our first Property. By default, Properties are readable (the Get part) and writable (the Set path). However, they can also be declared as ReadOnly (only Get part) or WriteOnly (only Set part). Also, some Attributes can be specified. In this case, Category (existing or new, where the Property is to be included) and Description (the explanation that appears at the bottom of the Properties Window). For reading a property, Return the value of the associated variable. For writing a property, set it's associated variable to the specified value, and, if the value is to take immediate effect, code the action. In this case, just a call to the Sub ShowHideList, with the argument True, to set the variable _ShowList and Drop-down the List:
VB
<Category("_MCCB specifics")> _
<Description("Maximum Items Displyed by the List")> _
    Public Property MaxItemsDisp() As Byte
        Get
            ' Get - if the Property is readable (or ReadOnly)
            Return _MaxItemsDisp
        End Get
        Set(ByVal value As Byte)
            ' Set - if the Property is writable (or WriteOnly)
            _MaxItemsDisp = value
            ShowHideList(True) ' Action
        End Set
    End Property
  1. For now, let's create our first Method, which will allow adding Columns and set some (fixed) Properties. To be accessible from the outside, the Method must be Public. The first call to this Method will not create a new Column, but change the one already existing. The Method will accept three parameters:
  1. Width - Required. The Width of the Column, in pixels. A value of 0 will create a hidden Column.
  2. Text - Required. The title (Header) of the Column.
  3. Align - Optional. The Horizontal Alignment of the Column. Default (if not specified) is Left. HorizontalAlignment values (0=Left, 1=Right, 2=Center) are used to define the TextAlign property of ListView Columns (or, e.g., TextBoxes). However, Labels use other values (ContentAlignment), which besides the Horizontal position, also reflects the Vertical position (Top, Middle, Bottom). Our 'Headers' and 'Boxes' are to be 'middle' aligned, so HorizontalAlignment values (0, 1 and 2) must be transformed in 'Middle' ContentAlignment values (respectively 16, 64 and 32).
VB
Public Sub AddColumn(Width As Integer, Text As String, _
                     Optional Align As HorizontalAlignment = 0)
    Dim Lbl_Align As ContentAlignment = If(Align = 1, 64, _
                                           If(Align = 2, 32, 16))
    Dim Hdr As Label
    Dim Box As Label
    Me.SuspendLayout()
    _ColumnCount += 1
    _ColumnIndex = _ColumnCount - 1
    If _ColumnCount = 1 Then   ' First Column, already exists
        Hdr = Hdr0                          ' Existing Header
        Box = Box0                          ' Existing Box
        MyLV.Width = Width + 19             ' Existing List. Initial
        ' value, including the "Button" (LblDrop)
        lvCol0.Width = Width - 3            ' Existing ListView Column
        _TotalWidth = Width - 1             ' Initial value
        Me.BackColor = Color.Transparent
    Else                        ' Column is to be created
        Hdr = New Label                         ' New Header
        Hdr.Name = "Hdr" & _ColumnIndex.ToString
        Hdr.Left = _TotalWidth
        Box = New Label                         ' New Box
        Box.Name = "Box" & _ColumnIndex.ToString
        Box.Left = _TotalWidth
        MyLV.Columns.Add(New ColumnHeader)      ' New ListView Column
        MyLV.Columns(_ColumnIndex).Name = "lvCol" & _ColumnIndex.ToString
        MyLV.Columns(_ColumnIndex).Text = ""
        MyLV.Columns(_ColumnIndex).Width = Math.Max(Width - 1, 0)
        MyLV.Columns(_ColumnIndex).TextAlign = Align
        MyLV.Width += Width - 1     ' Accum.
        _TotalWidth += Width - 1    ' Accum.
    End If
    Hdr.Width = Width           ' Header
    Hdr.Text = Text
    Hdr.TextAlign = Lbl_Align
    Box.Width = Width           ' Box
    Box.Text = ""
    Box.TextAlign = Lbl_Align
    LblDrop.Left = _TotalWidth  ' DropDown "Button"
    LblDrop.Height = _BoxHeight
    If _ColumnCount > 1 Then    ' All but first
        Controls.AddRange({Box, Hdr})
    End If
    Me.ResumeLayout(True)
    RedrawControls()
End Sub

Example of how to call this Method:

VB
Mccb1.AddColumn(140, "Name")    ' Align not specified = HorizontalAlignment.Left
Mccb1.AddColumn(35, "Age", HorizontalAlignment.Center)
Mccb1.AddColumn(90, "Due date", 2)  ' 2 = HorizontalAlignment.Center
Mccb1.AddColumn(90, "Amount (US$)", HorizontalAlignment.Right)
  1. As said before, AddColumn Method creates new Columns, setting up their unalterable Properties. But to properly complete the Components setup, we have to initialize the Properties that can be changed at any time. Therefore, we'll create a specific (Private) Subroutine (RedrawControls), which is also called by the AddColumn Method (last instruction): Note that, because the Size of the Control is changed (Me.Height & Me.Width), the Control's Resize Event will be raised:
VB
Private Sub RedrawControls()
    Me.SuspendLayout()
    MyLV.Top = _HeaderHeight + _BoxHeight - 2
    MyLV.BackColor = _ListBackColor
    MyLV.ForeColor = _ListForeColor
    MyLV.BorderStyle = _ListBorderStyle
    Dim Name As String
    For iCtr As Integer = 0 To _ColumnIndex ' For each Column...
        Name = "Box" & iCtr.ToString
        Controls(Name).Top = _HeaderHeight - 1
        Controls(Name).Height = _BoxHeight
        Controls(Name).BackColor = _BoxBackColor
        Controls(Name).ForeColor = _BoxForeColor
        Dim Lbl As Label = CType(Controls(Name), Label)
        Lbl.BorderStyle = _BoxBorderStyle
        Name = "Hdr" & iCtr.ToString
        Controls(Name).Height = _HeaderHeight
        Controls(Name).BackColor = _HeaderBackColor
        Controls(Name).ForeColor = _HeaderForeColor
        Lbl = CType(Controls(Name), Label)
        Lbl.BorderStyle = _HeaderBorderStyle
    Next
    LblDrop.Top = _HeaderHeight - 1
    LblDrop.Height = _BoxHeight
    _Me_MinHeight = _HeaderHeight + _BoxHeight - 1
    Me.Height = _Me_MinHeight
    Me.Width = _TotalWidth + 20 ' 20=LblDrop.Width
    Me.ResumeLayout(True)
End Sub
  1. Look at the provided Source Project. Code or copy all the other Properties which call RedrawControls. Special attention to two Properties whose action is different: The first, ListFontStyle, whose Type is defined by the Enum LFStyle, sets the variable _ListFontStyle and calls the Event (FontChanged) that occurs whenever the Font changes. The second, LayerOrder, whose Type is defined by the Enum LayOrder, sets the variable _LayerOrder, but its action is taken before, depending on its previous value. Why? Because, if a and b offer no doubts, setting the value to 0 (Normal) implies to change the last behavior. That action must also be taken when the Control is loaded, in the Control's Load Event. Let's see the Load and the FontChanged Events, and the two Properties:
VB
Private Sub MCCB_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    If _LayerOrder = 1 Then
        Me.BringToFront()
    ElseIf _LayerOrder = 2 Then
        Me.SendToBack()
    End If
End Sub
VB
Private Sub MCCB_FontChanged(sender As Object, e As EventArgs) Handles Me.FontChanged
    MyLV.Font = New Font(Me.Font, If(_ListFontStyle = 0, _
                                    Me.Font.Style, FontStyle.Regular))
End Sub
VB
<Category("_MCCB specifics")> _
<Description("Action in List when Control's Font changes to Bold")> _
Public Property ListFontStyle() As LFStyle
    Get
        Return _ListFontStyle
    End Get
    Set(ByVal value As LFStyle)
        _ListFontStyle = value
        MCCB_FontChanged(Nothing, Nothing)
    End Set
End Property
VB
<Category("_MCCB specifics")> _
<Description("Control's Layer Order Action")> _
Public Property LayerOrder() As LayOrder
    Get
        Return _LayerOrder
    End Get
    Set(ByVal value As LayOrder)
        If value = 1 OrElse (value = 0 And _LayerOrder = 2) Then
            Me.BringToFront()
        ElseIf value = 2 OrElse (value = 0 And _LayerOrder = 1) Then
            Me.SendToBack()
        End If
        _LayerOrder = value
    End Set
End Property
  1. Let's create a Method to feed the List. It requires an array of Strings, one for each SubItem, including any hidden Columns. It's simple, because such array is directly convertible in the required ListViewItem type. A Boolean is returned, indicating the Success (True) or Failure (False) of the operation:
VB
Public Function AddRow(SubItems As Array) As Boolean
    Dim OK As Boolean = False
    If SubItems.Length > _ColumnIndex + 1 Then
        MsgBox("SubItems (" & SubItems.Length.ToString & _
               ") exceeds the number of Columns (" & _
               (_ColumnIndex + 1).ToString & ")...", _
               MsgBoxStyle.Critical, _Error)
    Else
        Try
            MyLV.Items.Add(New ListViewItem(SubItems))
            _ItemsCount += 1
            OK = True
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Critical, _Error)
        End Try
    End If
    Return OK
End Function

Example of how to call this Method:

VB
Dim vAge As Byte = 35
Dim vDate As String = Today.ToShortDateString
Dim vValue As Single = 1234.56
If Mccb1.AddRow({"John Smith", vAge.ToString, vDate, Format(vValue, "#,###.00")}) = False Then
   ' Something went wrong...
End If
  1. When a List Row is selected, the SubItem(s) of the Row must be shown in the corresponding Box(es). To perform the task, let's create a Sub ShowSelectedItem, as well as the three situations where the task is to be performed: 1-Our Control's Property (Non-browsable and hidden) SelectedIndex, 2-our Control's Method FindNextItem and 3-the ListView Event ItemSelectionChanged., which fires our Control's Event (ItemSelectionChanged) (code fragment #1) that is to be raised whenever a new Row is selected and provides an array of Strings with the values of all the SubItems of the selected Row, also a simple Sub () (code fragment #2) used to display an error message when an invalid negative index is detected, and a Function (GetSubItems) that prepares the above mentioned array of Strings, also used in Method FindNextItem:
VB
Public Event ItemSelectionChanged(SubItems As Array)
VB
Private Sub MsgNoNeg(Prefx As String)
    MsgBox(Prefx & " cannot be negative...", _
           MsgBoxStyle.Critical, _Error)
End Sub
VB
Private Sub ShowSelectedItem()
    Dim BoxName As String
    For iCtr As Integer = 0 To _ColumnIndex
        BoxName = "Box" & iCtr.ToString
        Controls(BoxName).Text = MyLV.Items(_SelectedIndex).SubItems(iCtr).Text
    Next
End Sub
VB
Private Function GetSubItems() As Array
    Dim SubItems(_ColumnIndex) As String
    For iSI As Integer = 0 To _ColumnIndex
        SubItems(iSI) = MyLV.Items(_SelectedIndex).SubItems(iSI).Text
    Next
    Return SubItems
End Function
VB
 <Browsable(False)> _
<DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Property SelectedIndex() As Integer
    Get
        Return _SelectedIndex
    End Get
    Set(ByVal value As Integer)
        If value < 0 Then
            MsgNoNeg("Index")
        Else
            If value >= _ItemsCount Then
                MsgBox("Last Index = " & (_ItemsCount - 1).ToString, _
                       MsgBoxStyle.Critical, _Error)
            Else
                If _SelectedIndex >= 0 Then
                    MyLV.Items(_SelectedIndex).Selected = False
                End If
                _SelectedIndex = value
                MyLV.Items(_SelectedIndex).Selected = True
                ShowSelectedItem()
                ShowHideList(Show:=False)    'Close List
            End If
        End If
    End Set
End Property
VB
Public Function FindNextItem(ColumnIndex As Integer, SearchString As String) As Array
    Dim FoundItem(_ColumnIndex) As String
    If ColumnIndex >= 0 Then
        If ColumnIndex > _ColumnIndex Then
            MsgBox("Maximum ColumnIndex is " & _ColumnIndex.ToString & "...", _
                   MsgBoxStyle.Critical, _Error)
        Else
            If ColumnIndex = _FNIlastIdx And SearchString = _FNIlastStr Then
                ' Same values, serch next
                _FNI_iFrom += 1
            Else
                ' New values, search first
                _FNI_iFrom = 0
                _FNIlastIdx = ColumnIndex
                _FNIlastStr = SearchString
            End If
            If _FNI_iFrom >= 0 Then

                Dim Found As Boolean = False
                Dim iCtr As Integer
                For iCtr = _FNI_iFrom To _ItemsCount - 1
                    If Strings.InStr(MyLV.Items(iCtr).SubItems(ColumnIndex).Text, _
                                     SearchString, CompareMethod.Text) > 0 Then
                        ' Item found...
                        Found = True
                        _SelectedIndex = iCtr
                        FoundItem = GetSubItems()
                        ' Select Item
                        If _SelectedIndex >= 0 Then
                            MyLV.Items(_SelectedIndex).Selected = False
                        End If
                        MyLV.Items(_SelectedIndex).Selected = True
                        ShowSelectedItem()
                        ShowHideList(True)
                        Exit For
                    End If
                Next
                _FNI_iFrom = iCtr
                If Found = False And iCtr = _ItemsCount Then
                    MsgBox("No match...", MsgBoxStyle.Information, "Info")
                    FoundItem = Nothing
                End If
            End If
        End If
    Else
        MsgNoNeg("ColumnIndex")
    End If
    Return FoundItem
End Function
VB
Private Sub MyLV_ItemSelectionChanged(sender As Object, e As ListViewItemSelectionChangedEventArgs) _
            Handles MyLV.ItemSelectionChanged
    Dim FoundItem(_ColumnIndex) As String
    If e.IsSelected Then
        _SelectedIndex = e.ItemIndex
        ShowSelectedItem()
        ShowHideList(False)     ' Close List
        RaiseEvent ItemSelectionChanged(GetSubItems)
    End If
End Sub
  1. Just two more simple Methods, Clear and DropDown:
VB
Public Sub Clear()
    MyLV.Items.Clear()
    _ItemsCount = 0
    For iCtr As Integer = 0 To _ColumnIndex
        Controls("Box" & iCtr.ToString).Text = ""
    Next
    ShowHideList(False)     ' Close the List
End Sub
VB
Public Sub DropDown()
    ShowHideList(True)      ' Drop-down the List
End Sub

That's all. I organized the Control's Code in Regions:

VB
Imports
Enums & Variables
Public Properties
Public Methods
Public Event
Control Events
Private Subs/Functions
Initialization

#Region "Initialization" is the code generated by the Designer.

Finally, in your WinForms Application:

  1. Copy MCCB.dll to its StartupPath ( \bin\Debug or \bin\Release within the Project ) , and after to the Folder of your final .EXE
  2. In Visual Studio, Add a Reference: Menu PROJECT - Add Reference... - Browse... - MCCB.dll
  3. Put an Icon ( Image 4 ) in the Toolbox: Menu TOOLS - Choose Toolbox Items... - .NET Framework Components - Browse... - MCCB.dll . The Icon will appear under All Windows Forms group.

Brief description of the Control's own Properties, Methods and Event

Properties

  • BoxBackColor - Back Color of the Box(es).
  • BoxBorderStyle - Border Style of the Box(es).
  • BoxForeColor - Fore Color of the Box(es).
  • BoxHeight - Height of the Box(es).
  • HeaderBackColor - Back Color of the Header(s).
  • HeaderBorderStyle - Border Style of the Header(s).
  • HeaderForeColor - Fore Color of the Header(s).
  • HeaderHeight - Height of the Header(s).
  • LayerOrder - Control's Layer Order Action.
  • ListBackColor - Back Color of the List.
  • ListBorderStyle - Border Style of the List.
  • ListFontStyle - Action in List when Control's Font changes to Bold.
  • ListForeColor - Fore Color of the List.
  • MaxItemsDisp - Maximum Items Displayed by the List.
  • SelectedIndex - Index of the Item that is (or is to be) Selected in the List.

Methods

  • AddColumn(Width As Integer, Text As String, [Align As HorizontalAlignment = HorizontalAlignment.Left]) - Adds a Column, given its Width (in pixels), its (header)Text and its Alignment (Left, Center, Right).
  • AddRow(SubItems As Array) As Boolean - Adds a Row to the List, given an array of Strings. Returns a Boolean indicating Success (True) or Failure (False) of the operation.
  • Clear - Clears the List and the Box(es) of the Control.
  • DropDown - Drops Down the List.
  • FindNextItem(ColumnIndex As Integer, SearchString As String) As Array - Finds the next occurrence of a given String within the values of a Column, given its Index. The Row where the match occurs is selected and an array of its SubItems is returned. When no more matches, the array is Nothing, but the last selected Row remains selected.

Event

  • ItemSelectionChanged(SubItems As Array) - Occurs whenever a new Row is selected from the List.

History

09.Mar.2016 - First post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)