Introduction
This is ready-to-use code which helps you create your own UITypeEditor
s 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):
<Editor(GetType(MyPropertyEditor),
GetType(System.Drawing.Design.UITypeEditor))>
Some samples are shown in the following images:
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:
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:
Imports System.Drawing
Imports System.Drawing.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
Imports System.ComponentModel
Public MustInherit Class PropertyEditorBase
Inherits System.Drawing.Design.UITypeEditor
Protected MustOverride Function GetEditControl(ByVal PropertyName As _
String, ByVal CurrentValue As Object) As Control
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
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 End If
Catch
End Try
Return UITypeEditorEditStyle.DropDown
End Function
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
IEditorService = DirectCast( _
provider.GetService(GetType(IWindowsFormsEditorService)), _
IWindowsFormsEditorService)
If IEditorService IsNot Nothing Then
Dim PropName As String = context.PropertyDescriptor.Name
m_EditControl = Me.GetEditControl(PropName, value)
If m_EditControl IsNot Nothing Then
m_EscapePressed = False
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 value
Else Return GetEditedValue(m_EditControl, PropName, value)
End If
End If
End If
End If
Catch ex As Exception
End Try
Return MyBase.EditValue(context, provider, value)
End Function
Public Function GetIWindowsFormsEditorService() As _
IWindowsFormsEditorService
Return IEditorService
End Function
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
It has two MustOverride (abstract) functions which should be defined by driven class. these are:
Function GetEditControl(ByVal PropertyName As String, _
ByVal CurrentValue As Object) As Control
and
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:
Imports System.ComponentModel
Public Class XTextBoxA
Inherits TextBox
Private m_myProperty As String = ""
<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
Public Class myListBoxPropertyEditor
Inherits PropertyEditorBase
Private WithEvents myListBox As New ListBox
Protected Overrides Function GetEditControl(ByVal PropertyName As String, _
ByVal CurrentValue As Object) As Control
myListBox.BorderStyle = System.Windows.Forms.BorderStyle.None
myListBox.Items.Clear() myListBox.Items.Add("AAA")
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 End Function
Private Sub myTreeView_Click(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles myListBox.Click
Me.CloseDropDownWindow() 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.