Click here to Skip to main content
15,886,026 members
Articles / Programming Languages / Visual Basic
Article

A Checked Listbox Collection Editor

Rate me:
Please Sign up or sign in to vote.
4.22/5 (8 votes)
23 Feb 2008CPOL1 min read 65K   1.3K   38   3
Implements a custom, checked listbox editor in a property grid.

Introduction

This code demonstrates how to create a custom property editor particularly suitable for key/value pairs of information. It implements IWindowsFormsEditorService and UITypeEditorEditStyle, which are used to create a custom property grid control.

Background

Several existing projects demonstrate how to create a custom ListBox, but I could not find any that demonstrated a checked ListBox, so I came up with my own.

Using the Code

The My.PropertyGridControls.CheckedListBoxEditor custom property editor is used in conjunction with a custom properties class bound to a property grid.



VB.NET
Imports System
Imports System.ComponentModel
Imports System.Windows.Forms.Design
Imports System.Windows.Forms
Imports System.Collections.Specialized

Namespace My.PropertyGridControls

    #Region "CheckedListBoxEditor"
    ''' <summary>
    ''' The control displayed in the property grid
    ''' </summary>
    ''' <remarks></remarks>
    Public Class CheckedListBoxEditor

        ''' <summary>
        ''' The default text displayed in the property grid "value" column
        ''' </summary>
        ''' <remarks></remarks>
        Private _strValue As String = "(Collection)"

        ''' <summary>
        ''' Creates a custom property editor using the CheckedListBoxEditor class
        ''' as the UITypeEditor
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        <Description("This property contains the checked ListBox collection."), _
            EditorAttribute(GetType(CheckedListBoxUITypeEditor), _
                GetType(System.Drawing.Design.UITypeEditor))> _
            Public Property CheckedListBoxCollectionProperty() As String
            Get
                Return _strValue
            End Get
            Set(ByVal value As String)
                _strValue = "(Collection)"
            End Set
        End Property

    End Class
    #End Region

    #Region "CheckedListBoxUITypeEditor"
     ''' <summary>
    ''' Custom, editable checked ListBox control
    ''' </summary>
    ''' <remarks>This demo loads a comma-delimited string collection of URLs
    ''' and boolean values to set the checked state for each item.</remarks>
    Public Class CheckedListBoxUITypeEditor
        Inherits System.Drawing.Design.UITypeEditor
        Public WithEvents cbx As New CheckedListBox
        Private es As IWindowsFormsEditorService

        ''' <summary>
        ''' Override the UITypeEditorEditStyle to return the editor style:
        ''' drop-down, modal, or none
        ''' </summary>
        ''' <param name="context"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads Overrides Function GetEditStyle_
            (ByVal context As System.ComponentModel.ITypeDescriptorContext) _
                As System.Drawing.Design.UITypeEditorEditStyle

            'returns the editor style:  drop-down, modal, or none
            Return System.Drawing.Design.UITypeEditorEditStyle.DropDown

        End Function

        ''' <summary>
        ''' Override whether or not the ListBox control should be resizable
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads Overrides ReadOnly Property IsDropDownResizable() As Boolean
            Get
                'if set to true, adds a grip to the lower left portion of the ListBox,
                'which makes the ListBox resizable as run time
                Return True

            End Get
        End Property

        ''' <summary>
        ''' Override the default method for editing values in the ListBox
        ''' </summary>
        ''' <param name="context"></param>
        ''' <param name="provider"></param>
        ''' <param name="value"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads Overrides Function EditValue_
            (ByVal context As System.ComponentModel.ITypeDescriptorContext, _
            ByVal provider As System.IServiceProvider, ByVal value As Object) As Object

            'instantiate the custom property editor service provider
            es = DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)), _
                IWindowsFormsEditorService)

            If es IsNot Nothing Then

                'load the ListBox items
                LoadListBoxItems()

                'sort the items
                cbx.Sorted = True

                'show the control
                es.DropDownControl(cbx)

            End If

            'ensure function returns a value on all code paths
            Return Nothing

        End Function

        ''' <summary>
        ''' Save the ListBox key/value pairs to My.Settings.UrlList
        ''' </summary>
        ''' <param name="sender"></param>
        ''' <param name="e"></param>
        ''' <remarks></remarks>
        Private Sub bx_Leave(ByVal sender As Object, ByVal e As System.EventArgs) _
                Handles cbx.Leave
            'clear the old list
            My.Settings.UrlsList.Clear()

            With cbx
                'load the ListBox key/value pairs
                For i As Integer = 0 To .Items.Count - 1

                    Dim txt As String = .Items(i).ToString
                    Dim chk As String = .GetItemChecked(i).ToString

                    'concatenate the key/value pair
                    Dim combined As String = LCase(txt) & "," & LCase(chk)

                    If .Items(i).ToString IsNot "" Then

                        'add the concatenated string to the "UrlsList" string collection
                        My.Settings.UrlsList.Add(combined)

                    End If
                Next
            End With
            'save the config file
            My.Settings.Save()
        End Sub

        ''' <summary>
        ''' Loads My.Settings.UrlList comma-delimited string collection
        ''' into the custom collection editor.
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub LoadListBoxItems()
            'create an array list
            Dim a As New ArrayList

            'load the config file "UrlsList" string collection into the array
            For Each s As String In My.Settings.UrlsList

                'split the URL from the checked value
                a.Add(Split(s, ","))

            Next

            'create a hashtable, so we can refer to the items in a key/value pair format
            Dim h As New Hashtable

            'load the array into the hashtable
            For i As Integer = 0 To a.Count - 1

                'add the first array item as the key, the second as the value
                h.Add(CType(a.Item(i), Array).GetValue(0).ToString, _
                    CType(a.Item(i), Array).GetValue(1).ToString)

            Next

            'dispose of the array list
            a = Nothing

            'clear the ListBox items
            cbx.Items.Clear()

            'index the hashtable
            For Each de As DictionaryEntry In h

                'add the key/value pairs to the ListBox
                cbx.Items.Add(de.Key, CBool(de.Value))

            Next

            'dispose of the collection
            h = Nothing

        End Sub

    End Class
    #End Region

End Namespace

A StringCollection from the app.config settings file is used to load the items displayed in the ListBox. My.Settings.UrlsList items are stored as comma-delimited key/value pairs.

XML
<userSettings>
    <CheckedListBoxCollectionEditor.My.MySettings>
        <setting name="UrlsList" serializeAs="Xml">
            <value>
                <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                    <string>http://www.thefreedictionary.com/,true</string>
                    <string>http://medical-dictionary.thefreedictionary.com/,
                        true</string>
                    <string>http://legal-dictionary.thefreedictionary.com/,true</string>
                    <string>http://financial-dictionary.thefreedictionary.com/,
                        true</string>
                    <string>http://acronyms.thefreedictionary.com/,true</string>
                    <string>http://idioms.thefreedictionary.com/,true</string>
                    <string>http://encyclopedia2.thefreedictionary.com/,true</string>
                    <string>http://encyclopedia.thefreedictionary.com/,true</string>
                    <string>http://www.m-w.com/dictionary/,true</string>
                    <string>http://www.freedictionary.org/search/,true</string>
                    <string>http://www.yourdictionary.com/,true</string>
                    <string>http://en.wikipedia.org/wiki/,true</string>
                </ArrayOfString>
            </value>
        </setting>
    </CheckedListBoxCollectionEditor.My.MySettings>
</userSettings>

To use the control:

  • Create a form
  • Add a property grid
  • Instantiate the custom property editor, and
  • Bind it to the property grid

Remember to change the values in My.Settings.UrlsList accordingly. You can also replace LoadListBoxItems() with your own ListBox item-loading function.

VB.NET
''' <summary>
''' Sample form with a property grid whose selected object is the custom ListBox editor
''' </summary>
''' <remarks></remarks>
Public Class Form1

    Public Sub New()

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

        ' Add any initialization after the InitializeComponent() call.

        'create the custom checked ListBox editor
        Dim c As New My.PropertyGridControls.CheckedListBoxEditor

        'bind it to the property grid
        Me.PropertyGrid1.SelectedObject = c
    End Sub
End Class


The ListBox is made resizable by overriding the IsDropDownResizable() property, which is set to True in the demo.

VB.NET
''' <summary>
''' Override whether or not the ListBox control should be resizable
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Overloads Overrides ReadOnly Property IsDropDownResizable() As Boolean
    Get

        Return True

    End Get
End Property


If you prefer a non-resizable ListBox, simply change IsDropDownResizable() to False.

VB.NET
''' <summary>
''' Override whether or not the ListBox control should be resizable
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Overloads Overrides ReadOnly Property IsDropDownResizable() As Boolean
    Get
        'if set to true, adds a grip to the lower left portion of the ListBox,
        'which makes the ListBox resizable as run time
        Return False

    End Get
End Property


To Do

  • Allow in-place editing of the text strings
  • Add custom "add record" control to the bottom of the ListBox

History

  • Initial release

License

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


Written By
Other
United States United States
An instructional designer by trade, I have been a hobbyist developer since '96.

Comments and Discussions

 
Questionworking on current value of the object Pin
Stefano Manni26-Jul-14 6:41
Stefano Manni26-Jul-14 6:41 
AnswerRe: working on current value of the object Pin
toddmo9-Dec-14 9:53
toddmo9-Dec-14 9:53 
GeneralSuperb Pin
Alex_MBM21-Sep-08 20:27
Alex_MBM21-Sep-08 20:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.