通過實現一個用戶界面 (UI) 類型編輯器,您可以爲複雜的屬性類型提供自定義設計時體驗。
本演練說明如何爲一個自定義類型創作您自己的 UI 類型編輯器並使用 PropertyGrid 來顯示其編輯界面。
本演練中闡釋的任務包括:
- 定義自定義類型。
- 爲您的 UI 類型編輯器定義視圖控件。
- 定義一個從 UITypeEditor 派生的類。
- 重寫 GetEditStyle 方法以通知 PropertyGrid 編輯器將使用的編輯器樣式的類型。
- 重寫 EditValue 方法以處理用戶界面、用戶輸入處理和賦值。
若要將本演練中的代碼作爲單個清單復制,請參見如何:創建利用設計時功能的 Windows 窗體控件。
先決條件
- 擁有在安裝有 .NET Framework 的計算機上創建和運行 Windows 窗體應用程序項目的足夠權限。
定義自定義類型
您的自定義 UI 類型編輯器將顯示自定義類型。此類型可能比較複雜,也可能比較簡單。本演練將定義一個具有自定義設計時編輯行爲的簡單類型。此類型名爲 MarqueeLightShape,它是一個具有兩個值(Square 和 Circle)的 enum。
定義自定義枚舉類型
- 在您的 Windows 窗體控件的定義體中,定義 MarqueeLightShape 類型。
Visual Basic
' This defines the possible values for the MarqueeBorder
' control's LightShape property.
Public Enum MarqueeLightShape
Square
Circle
End Enum
定義視圖控件
您的自定義 UI 類型編輯器使用一個 Windows 窗體控件來顯示編輯界面。此控件名爲 LightShapeSelectionControl,它是從 UserControl 派生的。它的構造函數採用當前屬性值和一個對 IWindowsFormsEditorService 的引用。當用戶單擊一個選擇時,視圖控件對 IWindowsFormsEditorService 使用 CloseDropDown 方法來關閉下拉窗口。
定義視圖控件
- 在您的 Windows 窗體控件的定義體中,定義 LightShapeSelectionControl 控件。
Visual Basic
' 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.
InitializeComponent()
' 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 Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
' LightShape is the property for which this control provides
' a custom user interface in the Properties window.
Public Property LightShape() As MarqueeLightShape
Get
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)
MyBase.OnPaint(e)
Dim gCircle As Graphics = Me.circlePanel.CreateGraphics()
Try
Dim gSquare As Graphics = Me.squarePanel.CreateGraphics()
Try
' Draw a filled square in the client area of
' the squarePanel control.
gSquare.FillRectangle( _
Brushes.Red, _
0, _
0, _
Me.squarePanel.Width, _
Me.squarePanel.Height)
' 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.Clear(Me.circlePanel.BackColor)
gCircle.FillEllipse( _
Brushes.Blue, _
0, _
0, _
Me.circlePanel.Width, _
Me.circlePanel.Height)
' 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
Finally
gSquare.Dispose()
End Try
Finally
gCircle.Dispose()
End Try
End Sub
Private Sub squarePanel_Click( _
ByVal sender As Object, _
ByVal e As EventArgs)
Me.lightShapeValue = MarqueeLightShape.Square
Me.Invalidate(False)
Me.editorService.CloseDropDown()
End Sub
Private Sub circlePanel_Click( _
ByVal sender As Object, _
ByVal e As EventArgs)
Me.lightShapeValue = MarqueeLightShape.Circle
Me.Invalidate(False)
Me.editorService.CloseDropDown()
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
Me.SuspendLayout()
'
' 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.Controls.Add(squarePanel)
Me.Controls.Add(circlePanel)
Me.Name = "LightShapeSelectionControl"
Me.Size = New System.Drawing.Size(150, 80)
Me.ResumeLayout(False)
End Sub
#End Region
End Class
定義 UI 類型編輯器類
若要實現 UI 類型編輯器行爲,應從 UITypeEditor 基類派生。此類名爲 LightShapeEditor。
定義 UI 類型編輯器類
1. 通過引用 System.Design 程序集並導入 System.Drawing.Design 和 System.Windows.Forms.Design 命名空間來啓用對 .NET Framework 設計時支持的訪問。有關更多信息,請參見如何:在 Windows 窗體中訪問設計時支持。
2. 在您的 Windows 窗體控件的定義體中,定義 LightShapeEditor 類。
Visual Basic
' 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
重寫 GetEditStyle 方法
GetEditStyle 方法向設計環境指示您的 UI 類型編輯器實現的是哪種用戶界面。UITypeEditorEditStyle 類型中定義可以使用的值。LightShapeEditor 實現一個 DropDown UI 類型編輯器。
重寫 GetEditStyle 方法
- 在 LightShapeEditor 定義體中,重寫 GetEditStyle 方法以返回 DropDown。
Visual Basic
Public Overrides Function GetEditStyle( _
ByVal context As System.ComponentModel.ITypeDescriptorContext) _
As UITypeEditorEditStyle
Return UITypeEditorEditStyle.DropDown
End Function
重寫 EditValue 方法
EditValue 方法爲編輯您的自定義類型建立了設計環境和用戶界面之間的交互。EditValue 方法創建了一個視圖控件或模式對話框的實例,可供用戶用來編輯值。用戶完成編輯後,EditValue 方法會將值返回給設計環境。
如果是 LightShapeSelectionControl 之類的視圖控件,EditValue 方法可能會向視圖控件傳遞一個對 IWindowsFormsEditorService 的引用。當用戶選擇某個值後,視圖控件可以使用此引用來關閉它自己。對於模式對話框,則沒有必要這樣做,因爲窗體可以關閉它自己。
重寫 EditValue 方法
- 在 LightShapeEditor 定義體中,重寫 EditValue 方法。
Visual Basic
Public Overrides Function EditValue( _
ByVal context As ITypeDescriptorContext, _
ByVal provider As IServiceProvider, _
ByVal value As Object) As Object
If Not (provider Is Nothing) Then
editorService = _
CType(provider.GetService(GetType(IWindowsFormsEditorService)), _
IWindowsFormsEditorService)
End If
If Not (editorService Is Nothing) Then
Dim selectionControl As _
New LightShapeSelectionControl( _
CType(value, MarqueeLightShape), _
editorService)
editorService.DropDownControl(selectionControl)
value = selectionControl.LightShape
End If
Return value
End Function
重寫 PaintValue 方法
您可以通過重寫 PaintValue 方法來提供您的屬性值的圖形表示形式。
重寫 PaintValue 方法
- 在 LightShapeEditor 定義體中,重寫 PaintValue 方法。還要重寫 GetPaintValueSupported 方法以返回 true。
Visual Basic
' 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)
Else
e.Graphics.DrawEllipse(p, e.Bounds)
End If
End Using
End Sub
將您的 UI 類型編輯器附加到屬性
當您的 UI 類型編輯器可以隨時在自定義控件中使用後,將 LightShapeEditor 附加到某個屬性,基於 MarqueeLightShape 類型實現此屬性,然後對此屬性應用 EditorAttribute。
將您的 UI 類型編輯器附加到屬性
- 在您的控件定義體中,聲明一個名爲 LightShape 的 MarqueeLightShape 屬性。還需聲明一個名爲 lightShapeValue、類型爲 MarqueeLightShape 的實例字段來支持該屬性。對該屬性應用 EditorAttribute。
Visual Basic
Private lightShapeValue As MarqueeLightShape
<Category("Marquee"), _
Browsable(True), _
EditorAttribute(GetType(LightShapeEditor), _
GetType(System.Drawing.Design.UITypeEditor))> _
Public Property LightShape() As MarqueeLightShape
Get
Return Me.lightShapeValue
End Get
Set(ByVal value As MarqueeLightShape)
Me.lightShapeValue = value
End Set
End Property
private MarqueeLightShape lightShapeValue;
[Category("Marquee")]
[Browsable(true)]
[EditorAttribute(typeof(LightShapeEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public MarqueeLightShape LightShape
{
get
{
return this.lightShapeValue;
}
set
{
this.lightShapeValue = value;
}
}
測試您的 UI 類型編輯器
通過使用 SelectedObject 屬性來創建您的自定義控件的實例並將其附加到 PropertyGrid 控件,您可以測試您的 UI 類型編輯器。
如果您在使用 Visual Studio,則可以創建一個新的 Windows 應用程序項目,引用您的控件的程序集,然後將您的控件的一個實例添加到窗體。Visual Studio 中對此任務提供了廣泛的支持。 有關更多信息,請參見演練:使用自定義組件自動填充工具箱。
當您的控件的屬性在設計時顯示時,您可以選擇 LightShape 屬性,選中後,會出現一個下拉箭頭 ( )。單擊此箭頭,您的視圖控件將出現在屬性項下面。單擊圓圈或方框,選擇值。單擊後,視圖控件自動關閉,同時您選擇的值將出現在 PropertyGrid 中。
注意 |
在開發自定義 UITypeEditor 時,建議將內部版本號設置爲隨每次生成而遞增。這樣可以防止在設計環境中創建 UITypeEditor 的較舊的緩存版本。 |