This documentation is archived and is not being maintained.

Walkthrough: Implementing a UI Type Editor

You can provide a custom design-time experience for complex property types by implementing a user interface (UI) type editor.

This walkthrough explains how to author your own UI type editor for a custom type and display the editing interface by using a PropertyGrid.

Tasks explained in this walkthrough include:

  • Defining a custom type.

  • Defining a view control for your UI type editor.

  • Defining a class that derives from UITypeEditor.

  • Overriding the GetEditStyle method to inform the PropertyGrid of the type of editor style that the editor will use.

  • Overriding the EditValue method to handle the user interface, user input processing, and value assignment.

To copy the code in this walkthrough as a single listing, see How to: Create a Windows Forms Control That Takes Advantage of Design-Time Features.

In order to complete this walkthrough, you will need:

  • Sufficient permissions to be able to create and run Windows Forms application projects on the computer where the .NET Framework is installed.

Your custom UI type editor will display a custom type. This type could be complex or simple. For this walkthrough, you will define a simple type with custom design-time editing behavior. This type is called MarqueeLightShape, and it is an enum with two values, Square and Circle.

To define a custom enumeration type

  • In the body of your Windows Forms control's definition, define the MarqueeLightShape type.

    ' This defines the possible values for the MarqueeBorder 
    ' control's LightShape property. 
    Public Enum MarqueeLightShape
    End Enum

Your custom UI type editor displays the editing interface using a Windows Forms control. This control is named LightShapeSelectionControl, and it derives from UserControl. Its constructor takes the current property value and a reference to the IWindowsFormsEditorService. The view control uses the CloseDropDown method on IWindowsFormsEditorService to close the drop-down window when the user clicks on a selection.

To define a view control

  • In the body of your Windows Forms control's definition, define the LightShapeSelectionControl control.

    ' This control provides the custom UI for the LightShape property 
    ' of the MarqueeBorder. It is used by the LightShapeEditor. 
    Public Class LightShapeSelectionControl
        Inherits System.Windows.Forms.UserControl
       Private lightShapeValue As MarqueeLightShape = MarqueeLightShape.Square
        Private editorService As IWindowsFormsEditorService
       Private squarePanel As System.Windows.Forms.Panel
       Private circlePanel As System.Windows.Forms.Panel
       ' Required designer variable. 
       Private components As System.ComponentModel.Container = Nothing 
       ' This constructor takes a MarqueeLightShape value from the 
       ' design-time environment, which will be used to display 
       ' the initial state. 
        Public Sub New( _
        ByVal lightShape As MarqueeLightShape, _
        ByVal editorService As IWindowsFormsEditorService)
            ' This call is required by the Windows.Forms Form Designer.
            ' Cache the light shape value provided by the  
            ' design-time environment. 
            Me.lightShapeValue = lightShape
            ' Cache the reference to the editor service. 
            Me.editorService = editorService
            ' Handle the Click event for the two panels.  
            AddHandler Me.squarePanel.Click, AddressOf squarePanel_Click
            AddHandler Me.circlePanel.Click, AddressOf circlePanel_Click
        End Sub 
        Protected Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then 
                ' Be sure to unhook event handlers 
                ' to prevent "lapsed listener" leaks. 
                RemoveHandler Me.squarePanel.Click, AddressOf squarePanel_Click
                RemoveHandler Me.circlePanel.Click, AddressOf circlePanel_Click
                If (components IsNot Nothing) Then
                End If 
            End If 
        End Sub 
        ' LightShape is the property for which this control provides 
        ' a custom user interface in the Properties window. 
        Public Property LightShape() As MarqueeLightShape
                Return Me.lightShapeValue
            End Get 
            Set(ByVal Value As MarqueeLightShape)
                If Me.lightShapeValue <> Value Then 
                    Me.lightShapeValue = Value
                End If 
            End Set 
        End Property 
        Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            Dim gCircle As Graphics = Me.circlePanel.CreateGraphics()
                Dim gSquare As Graphics = Me.squarePanel.CreateGraphics()
                    ' Draw a filled square in the client area of 
                    ' the squarePanel control.
                    gSquare.FillRectangle( _
                    Brushes.Red, _
                    0, _
                    0, _
                    Me.squarePanel.Width, _
                    ' If the Square option has been selected, draw a  
                    ' border inside the squarePanel. 
                    If Me.lightShapeValue = MarqueeLightShape.Square Then
                        gSquare.DrawRectangle( _
                        Pens.Black, _
                        0, _
                        0, _
                        Me.squarePanel.Width - 1, _
                        Me.squarePanel.Height - 1)
                    End If 
                    ' Draw a filled circle in the client area of 
                    ' the circlePanel control.
                    gCircle.FillEllipse( _
                    Brushes.Blue, _
                    0, _
                    0, _
                    Me.circlePanel.Width, _
                    ' If the Circle option has been selected, draw a  
                    ' border inside the circlePanel. 
                    If Me.lightShapeValue = MarqueeLightShape.Circle Then
                        gCircle.DrawRectangle( _
                        Pens.Black, _
                        0, _
                        0, _
                        Me.circlePanel.Width - 1, _
                        Me.circlePanel.Height - 1)
                    End If 
                End Try 
            End Try 
        End Sub 
        Private Sub squarePanel_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs)
            Me.lightShapeValue = MarqueeLightShape.Square
        End Sub 
        Private Sub circlePanel_Click( _
        ByVal sender As Object, _
        ByVal e As EventArgs)
            Me.lightShapeValue = MarqueeLightShape.Circle
        End Sub
    #Region "Component Designer generated code" 
        '/ <summary>  
        '/ Required method for Designer support - do not modify  
        '/ the contents of this method with the code editor. 
        '/ </summary> 
        Private Sub InitializeComponent()
            Me.squarePanel = New System.Windows.Forms.Panel
            Me.circlePanel = New System.Windows.Forms.Panel
            ' squarePanel 
            Me.squarePanel.Location = New System.Drawing.Point(8, 10)
            Me.squarePanel.Name = "squarePanel" 
            Me.squarePanel.Size = New System.Drawing.Size(60, 60)
            Me.squarePanel.TabIndex = 2
            ' circlePanel 
            Me.circlePanel.Location = New System.Drawing.Point(80, 10)
            Me.circlePanel.Name = "circlePanel" 
            Me.circlePanel.Size = New System.Drawing.Size(60, 60)
            Me.circlePanel.TabIndex = 3
            ' LightShapeSelectionControl 
            Me.Name = "LightShapeSelectionControl" 
            Me.Size = New System.Drawing.Size(150, 80)
        End Sub
    #End Region
    End Class

To implement UI type editor behavior, derive from the UITypeEditor base class. This class is called LightShapeEditor.

To define a UI type Editor Class

  1. Enable access to .NET Framework design-time support by referencing the System.Design assembly and importing the System.Drawing.Design and System.Windows.Forms.Design namespaces. For more information, see How to: Access Design-Time Support in Windows Forms.

  2. In the body of your Window Forms control's definition, define the LightShapeEditor class.

    ' This class demonstrates the use of a custom UITypeEditor.  
    ' It allows the MarqueeBorder control's LightShape property 
    ' to be changed at design time using a customized UI element 
    ' that is invoked by the Properties window. The UI is provided 
    ' by the LightShapeSelectionControl class. 
    Friend Class LightShapeEditor
        Inherits UITypeEditor

The GetEditStyle method indicates to the design environment which kind of user interface your UI type editor implements. The possible values are defined in the UITypeEditorEditStyle type. The LightShapeEditor implements a DropDown UI type editor.

To override the GetEditStyle method

  • In the body of the LightShapeEditor definition, override the GetEditStyle method to return DropDown.

            Public Overrides Function GetEditStyle( _
            ByVal context As System.ComponentModel.ITypeDescriptorContext) _
            As UITypeEditorEditStyle
                Return UITypeEditorEditStyle.DropDown
            End Function

The EditValue method establishes the interaction between the design environment and the user interface for editing your custom type. The EditValue method creates an instance of the view control or the modal dialog box with which the user edits the value. When the user is finished editing, the EditValue method returns the value to the design environment.

In the case of a view control like LightShapeSelectionControl, the EditValue method may pass a reference to the IWindowsFormsEditorService to the view control. The view control can use this reference to close itself when the user selects a value. This is not necessary for a modal dialog box, because a form can close itself.

To override the EditValue method

  • In the body of the LightShapeEditor definition, override the EditValue method.

    Public Overrides Function EditValue( _
    ByVal context As ITypeDescriptorContext, _
    ByVal provider As IServiceProvider, _
    ByVal value As Object) As Object 
        If (provider IsNot Nothing) Then
            editorService = _
            CType(provider.GetService(GetType(IWindowsFormsEditorService)), _
        End If 
        If (editorService IsNot Nothing) Then 
            Dim selectionControl As _
            New LightShapeSelectionControl( _
            CType(value, MarqueeLightShape), _
            value = selectionControl.LightShape
        End If 
        Return value
    End Function

You can provide a graphical representation of your property's value by overriding the PaintValue method.

To override the PaintValue method

  • In the body of the LightShapeEditor definition, override the PaintValue method. Also override the GetPaintValueSupported method to return true.

    ' This method indicates to the design environment that 
    ' the type editor will paint additional content in the 
    ' LightShape entry in the PropertyGrid. 
    Public Overrides Function GetPaintValueSupported( _
    ByVal context As ITypeDescriptorContext) As Boolean 
        Return True 
    End Function 
    ' This method paints a graphical representation of the  
    ' selected value of the LightShpae property. 
    Public Overrides Sub PaintValue( _
    ByVal e As PaintValueEventArgs)
        Dim shape As MarqueeLightShape = _
        CType(e.Value, MarqueeLightShape)
        Using p As Pen = Pens.Black
            If shape = MarqueeLightShape.Square Then
                e.Graphics.DrawRectangle(p, e.Bounds)
                e.Graphics.DrawEllipse(p, e.Bounds)
            End If 
        End Using 
    End Sub

When your UI type editor is ready for use in your custom control, attach the LightShapeEditor to a property, implement the property based on the MarqueeLightShape type, and apply the EditorAttribute to the property.

To attach your UI type editor to a property

  • In the body of your control's definition, declare a MarqueeLightShape property named LightShape. Also declare an instance field named lightShapeValue of type MarqueeLightShape to back the property. Apply the EditorAttribute to the property.

Private lightShapeValue As MarqueeLightShape

<Category("Marquee"), _
Browsable(True), _
EditorAttribute(GetType(LightShapeEditor), _
GetType(System.Drawing.Design.UITypeEditor))> _
Public Property LightShape() As MarqueeLightShape
        Return Me.lightShapeValue
    End Get
    Set(ByVal value As MarqueeLightShape)
        Me.lightShapeValue = value
    End Set
End Property

You can test your UI type editor by creating an instance of your custom control and attaching it to a PropertyGrid control using the SelectedObject property.

If you are using Visual Studio, you can create a new Windows Application project, reference your control's assembly, and add an instance of your control to the form. There is extensive support for this task in Visual Studio. Walkthrough: Automatically Populating the Toolbox with Custom Components
Walkthrough: Automatically Populating the Toolbox with Custom Components
Walkthrough: Automatically Populating the Toolbox with Custom Components
Walkthrough: Automatically Populating the Toolbox with Custom Components

When the properties for your control are displayed at design time, you can select the LightShape property. When it is selected, a drop-down arrow (Properties Window Down Arrow) appears. When you click on the arrow, your view control appears beneath the property entry. Click on the circle or square to select the value. After you click, the view control dismisses itself, and the value you selected appears in the PropertyGrid.

Note Note

When you develop your custom UITypeEditor, it is recommended that you set the build number to increment with each build. This prevents older, cached versions of your UITypeEditor from being created in the design environment.

Once you have authored your own UI type editor, explore other ways to interact with a PropertyGrid and the design environment: