自定义UITypeEditor在Visual Studio设计模式中的应用

在Visual Studio集成开发环境中,开发者可以通过自定义UITypeEditor类来实现在设计模式下对控件属性进行编辑。UITypeEditor类允许开发者创建下拉列表(DropDown)或模态表单(ModalForm)窗口,以实现设计时的属性编辑。本文将介绍如何使用UITypeEditor类,并提供一个基类PropertyEditorBase来简化自定义编辑器的开发过程。

要使用UITypeEditor,首先需要从该类继承并为控件属性添加Editor属性。以下是一个VB.NET的示例: <Editor(GetType(MyPropertyEditor), GetType(System.Drawing.Design.UITypeEditor))> _ Public Property MyProperty As String 通过这种方式,可以为属性提供一个自定义的编辑器。

接下来,介绍PropertyEditorBase类。这是一个抽象类,继承自System.Drawing.Design.UITypeEditor。由于使用UITypeEditor类需要一些特殊代码,可以将这些代码放入一个基类(辅助类)中,以便后续更容易使用。

例如,当用户按下Esc键时,编辑过程应该被取消,并且之前的属性值应该返回到IDE的PropertyGrid中。或者,总是需要用一行代码获取IWindowsFormsEditorService服务: Dim IEditorService As IWindowsFormsEditorService = DirectCast(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService) 这些工作对于想要快速编写UITypeEditor的开发者来说可能不是很清楚。不会在这里详细说明,而是提供一个基类辅助类,以简化这个过程。

以下是PropertyEditorBase类的代码示例: 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 = GetEditControl(context.PropertyDescriptor.Name, context.PropertyDescriptor.GetValue(context.Instance)) If TypeOf c Is Form Then Return UITypeEditorEditStyle.Modal Else Return UITypeEditorEditStyle.DropDown End If Catch Return MyBase.GetEditStyle(context) End Try 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 Dim IEditorService As IWindowsFormsEditorService = 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 Return MyBase.EditValue(context, provider, value) End Try End Function Public Function GetIWindowsFormsEditorService() As IWindowsFormsEditorService Return IEditorService End Function Public Sub CloseDropDownWindow() If IEditorService IsNot Nothing Then IEditorService.CloseDropDown() End If 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 If End Sub End Class

PropertyEditorBase类有两个MustOverride(抽象)函数,需要由派生类定义。这两个函数是: Function GetEditControl(ByVal PropertyName As String, ByVal CurrentValue As Object) As Control Function GetEditedValue(ByVal EditControl As Control, ByVal PropertyName As String, ByVal OldValue As Object) As Object 第一个函数应该返回在属性编辑器窗口中使用的控件(例如一个简单的列表框),第二个函数应该返回正在编辑的属性的新值。派生类可以使用这些函数的参数信息来返回适当的值。例如,在ListBox示例中,基于属性的CurrentValue,下拉列表框的初始项被选中。

以下是一个使用PropertyEditorBase基类为'myProperty'属性定义编辑器的示例控件: 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

以下是myListBoxPropertyEditor类,它使用ListBox作为编辑控件: 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") ' ... Add other items... 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

应该在适当的事件中调用CloseDropDownWindow方法来关闭下拉编辑器窗口。对于ListBox,这是ListBox的Click事件,但对于TreeView,它可能是TreeView的DblClick事件。

可以使用这个基类来定义使用任何特殊控件的编辑器。例如,可以定义一个自定义UserControl,它显示一些图像(而不是文本风格的枚举列表),用于设置控制主控件图形视图的属性。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485