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.
Imports System
Imports System.ComponentModel
Imports System.Windows.Forms.Design
Imports System.Windows.Forms
Imports System.Collections.Specialized
Namespace My.PropertyGridControls
#Region "CheckedListBoxEditor"
Public Class CheckedListBoxEditor
Private _strValue As String = "(Collection)"
<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"
Public Class CheckedListBoxUITypeEditor
Inherits System.Drawing.Design.UITypeEditor
Public WithEvents cbx As New CheckedListBox
Private es As IWindowsFormsEditorService
Public Overloads Overrides Function GetEditStyle_
(ByVal context As System.ComponentModel.ITypeDescriptorContext) _
As System.Drawing.Design.UITypeEditorEditStyle
Return System.Drawing.Design.UITypeEditorEditStyle.DropDown
End Function
Public Overloads Overrides ReadOnly Property IsDropDownResizable() As Boolean
Get
Return True
End Get
End Property
Public Overloads Overrides Function EditValue_
(ByVal context As System.ComponentModel.ITypeDescriptorContext, _
ByVal provider As System.IServiceProvider, ByVal value As Object) As Object
es = DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)), _
IWindowsFormsEditorService)
If es IsNot Nothing Then
LoadListBoxItems()
cbx.Sorted = True
es.DropDownControl(cbx)
End If
Return Nothing
End Function
Private Sub bx_Leave(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles cbx.Leave
My.Settings.UrlsList.Clear()
With cbx
For i As Integer = 0 To .Items.Count - 1
Dim txt As String = .Items(i).ToString
Dim chk As String = .GetItemChecked(i).ToString
Dim combined As String = LCase(txt) & "," & LCase(chk)
If .Items(i).ToString IsNot "" Then
My.Settings.UrlsList.Add(combined)
End If
Next
End With
My.Settings.Save()
End Sub
Private Sub LoadListBoxItems()
Dim a As New ArrayList
For Each s As String In My.Settings.UrlsList
a.Add(Split(s, ","))
Next
Dim h As New Hashtable
For i As Integer = 0 To a.Count - 1
h.Add(CType(a.Item(i), Array).GetValue(0).ToString, _
CType(a.Item(i), Array).GetValue(1).ToString)
Next
a = Nothing
cbx.Items.Clear()
For Each de As DictionaryEntry In h
cbx.Items.Add(de.Key, CBool(de.Value))
Next
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.
<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.
Public Class Form1
Public Sub New()
InitializeComponent()
Dim c As New My.PropertyGridControls.CheckedListBoxEditor
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.
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
.
Public Overloads Overrides ReadOnly Property IsDropDownResizable() As Boolean
Get
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