Click here to Skip to main content
Click here to Skip to main content

Dynamic DropDown Properties on the PropertyGrid

, 19 Jul 2007
Rate this:
Please Sign up or sign in to vote.
Explains how to add a dynamic dropdown property to the propertygrid at runtime and gives a detailed exampl
Screenshot - DropdownProperty.png

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:

  1. PropertyGrid and DropDown properties
  2. Using PropertyGrid, Part I
  3. ShouldSerialize and Reset Methods

Using the code

Dynamic dropdown properties are composed of three distinct items:

  1. A global list of values
  2. A type converter
  3. 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
    'This class is global to the namespace and can be altered by our control.
    'It can also be read by our OptionConverter to provide a general type.
    'It has all the dangers of any global variable and 
    'can be accessed by other assemblies.
    Friend Shared OptionStringArray(0) As String 
    'Holds the options available in the dropdown
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 
    'This will act as a typeconverter and present 
    'our collection to the property grid
    Inherits StringConverter

    Public Overloads Overrides Function GetStandardValuesSupported( _
        ByVal context As ITypeDescriptorContext) As Boolean
        Return True 'True tells the propertygrid to display a combobox
    End Function
    Public Overloads Overrides Function GetStandardValuesExclusive( _
        ByVal context As ITypeDescriptorContext) As Boolean
        Return True 'True makes the combobox select only. 
                    'False allows free text entry.
    End Function
    Public Overloads Overrides Function GetStandardValues( _
    ByVal context As ITypeDescriptorContext) As StandardValuesCollection
        Return New StandardValuesCollection(GlobalClass.OptionStringArray) 
        'Exports our global collection of options
    End Function

End Class

Property definition

The property definition can be divided into three sections:

  1. The local variable
  2. The exposed property
  3. The default values

Local variable

The local variable simply holds the selected option.

Private _SelectedOption As String 'Holds the selected option

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 
    'Property displayed it the property grid
        Get
            Dim TempString As String = "" 
            'Holds our selected option for return

            If _SelectedOption Is Nothing Then 
            'If an option has not already been selected
                If GlobalClass.OptionStringArray.GetUpperBound(0) > 0 Then 
                'If there is more than 1 option
                    Array.Sort(GlobalClass.OptionStringArray) 
                   'Sort them alphabetically
                End If
                TempString = GlobalClass.OptionStringArray(0) 
                'Choose the first option (or the empty one)
            Else 'Otherwise, if the option is already selected
                TempString = _SelectedOption 
                'Choose the already selected value
            End If

            Return TempString 
            'Return the selected option, the first option, or an empty option
        End Get
        Set(ByVal Value As String)
            _SelectedOption = Value 
            'When a selection is made update the selected option
        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.

Screenshot - DropdownProperty2.png

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 
    'Sets a dynamic "DefualtValueAttribute" for the property
    'This uses a poorly documented feature of PropertyGrid and 
    'should be used in
    'conjunction with the Reset... method.
    '
    'When the PropertyGrid displays a value, it determines 
    'whether to show the value
    'in bold by checking first for a DefaultValueAttribute.
    '
    'If no DefaultValueAttribute is found, then the 
    'PropertyGrid uses reflection
    'to see if a method with the name ShouldSerialize... exists.
    '(where ... exactly matches the property name)
    '
    'If the method does exist, the PropertyGrid calls it. 
    'A return value of true
    'produces bold text, false produces regular text.

    Return Not _SelectedOption = GlobalClass.OptionStringArray(0)
End Function

Public Sub ResetOptionList() 
    'Resets to the dynamic "DefualtValueAttribute" for the Device
    'This uses a poorly documented feature of PropertyGrid and 
    'should be used in
    'conjunction with the ShouldSerialize... method.
    '
    'When the PropertyGrid resets a value, it determines the correct value
    'by checking first for a DefaultValueAttribute.
    '
    'If no DefaultValueAttribute is found then the 
    'PropertyGrid uses reflection
    'to see if a method with the name Reset... exists.
    '(where ... exactly matches the property name)
    '
    'If the method does exist, the propertygrid calls it 
    'to reset the property to
    'the default value.

    _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 'Holds number of options
Public Property NumberOfDynamicOptions() As Integer 
'Allows the number of options to change dynamically
    Get
        Return _NumberOfDynamicOptions 
        'Returns the current number of options displayed
    End Get
    Set(ByVal Value As Integer)
        If Value < 0 Then 'If the number entered is negative 
            _NumberOfDynamicOptions = 0 'Use zero instead
        ElseIf Value > 100 Then 'And if the number is over 100
            _NumberOfDynamicOptions = 100 'Just use 100
        Else 'Otherwise, if the number is between 0 and 100 (inclusive)
            _NumberOfDynamicOptions = Value 
            'Set it as our new number of options
        End If

        ReDim GlobalClass.OptionStringArray(_NumberOfDynamicOptions) 
        'Resize the array

        Dim LoopCount As Integer 'Loop variable
        For LoopCount = 0 To _NumberOfDynamicOptions 
            'Loop up to the number of options
            GlobalClass.OptionStringArray(LoopCount) = _
                LoopCount.ToString + " " + Chr(33 + LoopCount).ToString
            'Set each option equal to the count and a character
        Next
    End Set
End Property

History

  • 19 July, 2007 -- Original version posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Tyler W. Cox
Web Developer
United States United States
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.

Comments and Discussions

 
QuestionHow to incorporate into the dynamic PropertyGrid example? Pinmemberrcurrie25-Jul-07 7:00 
AnswerRe: How to incorporate into the dynamic PropertyGrid example? Pinmemberrcurrie25-Jul-07 8:20 
AnswerRe: How to incorporate into the dynamic PropertyGrid example? PinmemberTyler W. Cox25-Jul-07 14:03 
GeneralRe: How to incorporate into the dynamic PropertyGrid example? Pinmemberrcurrie25-Jul-07 14:09 
GeneralNeeded help for C# PinmemberMons211023-Jul-07 4:19 
AnswerRe: Needed help for C# PinmemberTyler W. Cox23-Jul-07 12:12 
QuestionAdding properties dynamically Pinmemberjayaveer_b322-Jul-07 21:14 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.141029.1 | Last Updated 19 Jul 2007
Article Copyright 2007 by Tyler W. Cox
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid