Introduction
Dropdown lists in the PropertyGrid provide an easy way to set up controls at design time. However, in some cases the options presented may not be known ahead of time or may vary based on some other setting. VB.NET does not provide an easy way to change the options available. This article gives a concise example of how to implement a dynamic dropdown property in the PropertyGrid.
Background
The code presented here brings together the following resources and combines them into a simple-to-use VB.Net solution:
- PropertyGrid and DropDown properties
- Using PropertyGrid, Part I
- ShouldSerialize and Reset Methods
Using the code
Dynamic dropdown properties are composed of three distinct items:
- A global list of values
- A type converter
- The property definition
Global values
In order for a list of values to appear in a dropdown list of the PropertyGrid, they must be accessible to our type converter. If we want to be able to change the list of values from within our class, they must also be accessable to the class. The solution to this is to place our list of values in an array located globally within the namespace. Here, we create a global class, GlobalClass
, which wraps a string array OptionStringArray
that will be used to hold the values displayed in our dropdown list.
Friend Class GlobalClass
Friend Shared OptionStringArray(0) As String
End Class
Type converter
A type converter provides a unified way of converting types of values into other types. The OptionConverter
overloads the GetStandardValuesSupported
, GetStandardValuesExclusive
, and GetStandardValues
methods of its inherited StingConverter
class. GetStandardValuesSupported
returns true
, indicating that the type supports standard values and that the PropertyGrid should display these values within a dropdown combo box. GetStandardValuesExclusive
returns true
to indicate that the standard values are locked and will not support freeform entry. GetStandardValues
returns the StandardValuesCollection
value created from GlobalClass.OptionStringArray
. This collection is what is used to populate the dropdown list.
Public Class OptionConverter
Inherits StringConverter
Public Overloads Overrides Function GetStandardValuesSupported( _
ByVal context As ITypeDescriptorContext) As Boolean
Return True
End Function
Public Overloads Overrides Function GetStandardValuesExclusive( _
ByVal context As ITypeDescriptorContext) As Boolean
Return True
End Function
Public Overloads Overrides Function GetStandardValues( _
ByVal context As ITypeDescriptorContext) As StandardValuesCollection
Return New StandardValuesCollection(GlobalClass.OptionStringArray)
End Function
End Class
Property definition
The property definition can be divided into three sections:
- The local variable
- The exposed property
- The default values
Local variable
The local variable simply holds the selected option.
Private _SelectedOption As String
Exposed property
OptionConverter
is passed to the type converter and presents the GlobqalClass.OtionStringArray
to the PropertyGrid as a selection list. If an item has already been selected and is in the local variable _SelectedOption
, it is returned by the Get
method. If no item is selected, then the first option is returned. When the Set
method is employed, the local variable _SelectedOption
is set to the value that is passed in.
<Browsable(True), TypeConverter(GetType(OptionConverter))> _
Public Property OptionList() As String
Get
Dim TempString As String = ""
If _SelectedOption Is Nothing Then
If GlobalClass.OptionStringArray.GetUpperBound(0) > 0 Then
Array.Sort(GlobalClass.OptionStringArray)
End If
TempString = GlobalClass.OptionStringArray(0)
Else
TempString = _SelectedOption
End If
Return TempString
End Get
Set(ByVal Value As String)
_SelectedOption = Value
End Set
End Property
Default values
Because DefaultValueAttribute
requires a constant and our dropdown property list is dynamic, we need to use an alternate method to provide a default value. This will both allow the dynamic default to appear in regular text in the property grid and allow the value to be reset to the default using the right click "reset" option.
Two methods are used to produce this behavior: ShouldSerializeOptionList()
and ResetOptionList()
. These methods must end in the exact same name as the exposed property or they will not work. If _SelectedOption
is equal the the desired default option, then false
should be returned by ShouldSerializeOptionList()
. Otherwise, ShouldSerializeOptionList()
should return true
to indicate that a bold font should be used. When ResetOptionList()
is called, the SelectedOption
should be changed back to the default option.
Public Function ShouldSerializeOptionList() As Boolean
Return Not _SelectedOption = GlobalClass.OptionStringArray(0)
End Function
Public Sub ResetOptionList()
_SelectedOption = GlobalClass.OptionStringArray(0)
End Sub
Points of interest
To change the contents of the dropdown list, redim the GlobalClass.OptionStringArray
to the desired size and set each element to the desired value. An example is provided below.
Private _NumberOfDynamicOptions As Integer
Public Property NumberOfDynamicOptions() As Integer
Get
Return _NumberOfDynamicOptions
End Get
Set(ByVal Value As Integer)
If Value < 0 Then
_NumberOfDynamicOptions = 0
ElseIf Value > 100 Then
_NumberOfDynamicOptions = 100
Else
_NumberOfDynamicOptions = Value
End If
ReDim GlobalClass.OptionStringArray(_NumberOfDynamicOptions)
Dim LoopCount As Integer
For LoopCount = 0 To _NumberOfDynamicOptions
GlobalClass.OptionStringArray(LoopCount) = _
LoopCount.ToString + " " + Chr(33 + LoopCount).ToString
Next
End Set
End Property
History
- 19 July, 2007 -- Original version posted
Tyler W. Cox has been coding for over 10 years. He received his degree in Computer Information Systems from USC and resides in Pueblo, Colorado where he manages a group of coders developing software for the telecommunications industry.