Click here to Skip to main content
15,881,173 members
Articles / Programming Languages / Visual Basic

Creating Property Editors in DesignTime for VS.Net Easily (UITypeEditor Helper)

Rate me:
Please Sign up or sign in to vote.
4.82/5 (40 votes)
18 Mar 2007CPOL2 min read 135.1K   2.8K   110   30
This is a base class to help easily create UITypeEditors. It is used to edit control properties in a DropDown window or a Modal-Form in design mode in the Visual Studio IDE

Introduction

This is ready-to-use code which helps you create your own UITypeEditors for design time editing of control properties in a DropDown or a ModalForm window at design mode in the Visual Studio IDE. To use it, inherits a class from it and add this attribute to your control property(ies):

VB.NET
<Editor(GetType(MyPropertyEditor), 
        GetType(System.Drawing.Design.UITypeEditor))>

Some samples are shown in the following images:

 

ListBox DropDown Editor TreeView DropDown Editor
Fig.1) Using a ListBox Editor Fig.2) Using a TreeView Editor

UserControl DropDown Editor

Fig.3) Using a UserControl Editor
ModalForm Editor
Fig.4) Using a Modal-Form Editor

The "PropertyEditorBase" Class

It is an abstract (MustInherit) class which is itself inherited from System.Drawing.Design.UITypeEditor. because using the UITypeEditor class requires some special code, we can put them into a base (helper) class and use it more easily later.

For example when the user presses the Esc key, the edit process should be canceled and previous property values should be returned to the IDE PropertyGrid. Or you always require to get the IWindowsFormsEditorService service with a line of code similar to:

VB.NET
IEditorService = 
   DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)),
                                  IWindowsFormsEditorService )

These jobs are not so clear for a developer who wants to write a UITypeEditor quickly. I won't speak more this and will just provide the base helper class you may use to simplify this process. (if you want to see just How To Use it, see This Section of the article.)

Here is the code:

VB.NET
Imports System.Drawing
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System.ComponentModel


''' <summary>

''' This is a UITypeEditor base class usefull for simple editing of control 
''' properties in a DropDown or a ModalForm window at design mode (in 
''' Visual Studio IDE). To use this, inherits a class from it and add this
''' attribute to your control property(ies): 
''' <Editor(GetType(MyPropertyEditor), 
'''         GetType(System.Drawing.Design.UITypeEditor))>  

''' </summary>

Public MustInherit Class PropertyEditorBase
    Inherits System.Drawing.Design.UITypeEditor

    ''' <summary>

    ''' The driven class should provide its edit Control to be shown in the 
    ''' DropDown or DialogForm window by means of this function. 
    ''' If specified control be a Form, it is shown in a Modal Form, otherwise 
    ''' in a DropDown window. This edit control should return its final value 
    ''' at GetEditedValue() method. 
    ''' </summary>

    Protected MustOverride Function GetEditControl(ByVal PropertyName As _
      String, ByVal CurrentValue As Object) As Control

    ''' <summary>The driven class should return the New Edited Value at this 

    ''' function.</summary>

    ''' <param name="EditControl">

    ''' The control shown in DropDown window and used for editing. 
    ''' This is the control you pass in GetEditControl() function.
    ''' </param>

    ''' <param name="OldValue">The original value of the property before 

    ''' editing</param>

    Protected MustOverride Function GetEditedValue(ByVal EditControl As _
      Control, ByVal PropertyName As String, _
               ByVal OldValue As Object) As Object

    Protected IEditorService As IWindowsFormsEditorService
    Private WithEvents m_EditControl As Control
    Private m_EscapePressed As Boolean

    ''' <summary>

    ''' Sets the edit style mode based on the type of EditControl: DropDown or
    ''' Modal(Dialog). 
    ''' Note that the driven class can also override this function and 
    ''' explicitly set its value.
    ''' </summary>

    Public Overrides Function GetEditStyle(ByVal context As _
                               ITypeDescriptorContext) As UITypeEditorEditStyle
        Try
            Dim c As Control
            c = GetEditControl(context.PropertyDescriptor.Name, _
                context.PropertyDescriptor.GetValue(context.Instance))
            If TypeOf c Is Form Then
                Return UITypeEditorEditStyle.Modal 'Using a Modal Form
            End If
        Catch
        End Try
        'Using a DropDown Window (This is the default style)
        Return UITypeEditorEditStyle.DropDown
    End Function

    'Displays the Custom UI (a DropDown Control or a Modal Form) for value 
    'selection.
    Public Overrides Function EditValue(ByVal context As ITypeDescriptorContext,_
      ByVal provider As IServiceProvider, ByVal value As Object) As Object

        Try
            If context IsNot Nothing AndAlso provider IsNot Nothing Then

                'Uses the IWindowsFormsEditorService to display a drop-down
                'UI in the Properties window:
                IEditorService = DirectCast( _
                provider.GetService(GetType(IWindowsFormsEditorService)), _
                                    IWindowsFormsEditorService)

                If IEditorService IsNot Nothing Then

                    Dim PropName As String = context.PropertyDescriptor.Name

                    'get Edit Control from driven class
                    m_EditControl = Me.GetEditControl(PropName, value) 

                    If m_EditControl IsNot Nothing Then

                        m_EscapePressed = False    

                        'Show given EditControl
                        If TypeOf m_EditControl Is Form Then
                            IEditorService.ShowDialog(CType(m_EditControl, Form))
                        Else
                            IEditorService.DropDownControl(m_EditControl)
                        End If

                        If m_EscapePressed Then    'return the Old Value 
                                                   '(because user press Escape)
                            Return value
                        Else 'get new (edited) value from driven class and 
                             'return it
                            Return GetEditedValue(m_EditControl, PropName, value)
                        End If

                    End If 'm_EditControl

                End If 'IEditorService

            End If 'context And provider

        Catch ex As Exception
            'we may show a MessageBox here...
        End Try
        Return MyBase.EditValue(context, provider, value)

    End Function

    ''' <summary>

    ''' Provides the interface for this UITypeEditor to display Windows Forms 
    ''' or to display a control in a DropDown area from the property grid 
    ''' control in design mode.
    ''' </summary>

    Public Function GetIWindowsFormsEditorService() As _
                                                   IWindowsFormsEditorService
        Return IEditorService
    End Function

    ''' <summary>Close DropDown window to finish editing</summary>

    Public Sub CloseDropDownWindow()
        If IEditorService IsNot Nothing Then IEditorService.CloseDropDown()
    End Sub

    Private Sub m_EditControl_PreviewKeyDown(ByVal sender As Object, _
                                 ByVal e As PreviewKeyDownEventArgs) _
                                      Handles m_EditControl.PreviewKeyDown
        If e.KeyCode = Keys.Escape Then m_EscapePressed = True
    End Sub

End Class

How To Use

It has two MustOverride (abstract) functions which should be defined by driven class. these are:

VB.NET
Function GetEditControl(ByVal PropertyName As String, _
                        ByVal CurrentValue As Object) As Control

and

VB.NET
Function GetEditedValue(ByVal EditControl As Control, _
                        ByVal PropertyName As String, _
                        ByVal OldValue As Object) As Object

The first should return the control to be used in property editor window (eg. a simple list box) and the second should return the new value for the property under edition. the driven class may use parameter information of these functions to return the proper value. For example in the ListBox sample, the initial item of the DropDown listbox is selected based on the CurrentValue of the property.

ListBox Editor Sample

Here is a sample control which uses this helper base class to define an Editor for its 'myProperty' property:

VB.NET
Imports System.ComponentModel

Public Class XTextBoxA
    Inherits TextBox

    Private m_myProperty As String = ""

    'This property uses our custom UITypeEditor: myListBoxPropertyEditor
    <EditorAttribute(GetType(myListBoxPropertyEditor), 
     GetType(System.Drawing.Design.UITypeEditor))> _
    Public Property myProperty() As String
        Get
            Return m_myProperty
        End Get
        Set(ByVal value As String)
            m_myProperty = value
        End Set
    End Property

End Class



' ////////////////////////////////////////////////////////////////////////////
'   myListBoxPropertyEditor => using a ListBox as EditControl
' ////////////////////////////////////////////////////////////////////////////
'
Public Class myListBoxPropertyEditor
    Inherits PropertyEditorBase

    Private WithEvents myListBox As New ListBox 'this is the control to be used 
                                                'in design time DropDown editor

    Protected Overrides Function GetEditControl(ByVal PropertyName As String, _
      ByVal CurrentValue As Object) As Control

        myListBox.BorderStyle = System.Windows.Forms.BorderStyle.None

        'Creating ListBox items... 
        'Note that as this is executed in design mode, performance is not 
        'important and there is no need to cache listbox items if they can 
        'change each time.
        myListBox.Items.Clear()    'clear previous items if any
        myListBox.Items.Add("AAA")
        '... Add other items...

        'Select current item based on CurrentValue of the property:
        myListBox.SelectedIndex = myListBox.FindString(CurrentValue)
        myListBox.Height = myListBox.PreferredHeight

        Return myListBox

    End Function


    Protected Overrides Function GetEditedValue(ByVal EditControl As Control, _
       ByVal PropertyName As String, ByVal OldValue As Object) As Object
        Return myListBox.Text 'return new value for property
    End Function


    Private Sub myTreeView_Click(ByVal sender As Object, ByVal e As _
                                     System.EventArgs) Handles myListBox.Click
        Me.CloseDropDownWindow() 'when user clicks on an item, the edit 
                                 'process is done.
    End Sub

End Class

You should call the CloseDropDownWindow method to close the DropDown editor window in an appropriate event. For a ListBox this is the ListBox "Click" event but for a TreeView it may be the TreeView "DblClick" event.

Note

You can use this base class to define Editors which use any special controls. For example you may define a custom UserControl which shows some images (instead of a text-style Enum list) for setting a property which controls the graphical view of your main control.

download the source code to see all four samples shown in Fig.1 to Fig.4

See Also

SmartTagDesigner Article: Helps developers to build customized design-time extensions for components and controls through smart tag designer panels.

License

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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Tokinabo31-Jul-20 17:09
professionalTokinabo31-Jul-20 17:09 
QuestionHow would I load the myListboxPropertyEditor.GetEditControl with values contained in XTextBoxA? Pin
jviper24-Sep-18 7:28
jviper24-Sep-18 7:28 
QuestionÇok teşekkürler... Pin
anemos_7825-Apr-17 16:33
anemos_7825-Apr-17 16:33 
QuestionExactly what I was searching Pin
Jorge Barquero10-Apr-17 18:27
Jorge Barquero10-Apr-17 18:27 
GeneralMy vote of 5 Pin
karenpayne12-Dec-13 6:56
karenpayne12-Dec-13 6:56 
GeneralMy vote of 5 Pin
Flintstone-Fred24-Sep-10 13:02
Flintstone-Fred24-Sep-10 13:02 
QuestionUpdating Designer when Property Changed Pin
stixoffire22-Apr-09 9:31
stixoffire22-Apr-09 9:31 
GeneralThis example is excellent but... Pin
Gabriel Giani30-Nov-08 2:23
Gabriel Giani30-Nov-08 2:23 
GeneralDesign-Time Property Question Pin
Elkay9-Jul-08 9:41
Elkay9-Jul-08 9:41 
QuestionFilter Listbox data [modified] Pin
aguidas12-Sep-07 8:09
aguidas12-Sep-07 8:09 
GeneralModal form doesn't work Pin
aermec31-Jul-07 20:28
aermec31-Jul-07 20:28 
GeneralRe: Modal form doesn't work Pin
micTronic16-Oct-07 1:43
micTronic16-Oct-07 1:43 
GeneralRe: Modal form doesn't work Pin
micTronic16-Oct-07 2:17
micTronic16-Oct-07 2:17 
GeneralRe: Modal form doesn't work fixed Pin
errorfunktion8-Nov-08 7:43
errorfunktion8-Nov-08 7:43 
GeneralThanks & C# version Pin
User 19428922-Jun-07 6:55
User 19428922-Jun-07 6:55 
GeneralRe: Thanks & C# version [modified] Pin
User 19428915-Aug-07 1:39
User 19428915-Aug-07 1:39 
GeneralBroken download link Pin
mrlucmorin6-Mar-07 6:42
mrlucmorin6-Mar-07 6:42 
GeneralFixed Pin
Chris Maunder18-Mar-07 11:19
cofounderChris Maunder18-Mar-07 11:19 
GeneralRe: Fixed Pin
mrlucmorin26-Mar-07 2:09
mrlucmorin26-Mar-07 2:09 
GeneralSource Pin
hipsvin26-Jan-07 1:38
hipsvin26-Jan-07 1:38 
GeneralThanks Pin
Polymorpher21-Jan-07 11:21
Polymorpher21-Jan-07 11:21 
GeneralWell done Pin
siroman14-Jan-07 20:39
siroman14-Jan-07 20:39 
GeneralWill add a reference to your article Pin
visualhint10-Jan-07 5:13
visualhint10-Jan-07 5:13 
GeneralRe: Will add a reference to your article Pin
S.Serpooshan13-Jan-07 8:40
S.Serpooshan13-Jan-07 8:40 
hi i want just to inform you that this article is updated. new features and samples are available now! you may want to take a look...
Also here is my new article: SmartTagDesigner[^]
Generalvery nice Pin
devnet2479-Jan-07 22:28
devnet2479-Jan-07 22:28 

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.