Passo a passo: Implementando um Editor UI de tipo
Você pode fornecer uma experiência de tempo de design personalizada para tipos de propriedade complexa, Implementando um editor de tipo de interface (UI) do usuário.
Esta explicação passo a passo explica como criar seu próprio editor de tipos de interface do usuário para um tipo personalizado e exibir a interface de edição usando um PropertyGrid.
Tarefas explicadas essa explicação passo a passo incluem:
Definição de um tipo personalizado.
A definição de um controle de exibição para o seu editor de tipos de interface do usuário.
Definir uma classe que deriva de UITypeEditor.
Substituindo o GetEditStyle método para informar o PropertyGrid do tipo de estilo do editor que usará o editor.
Substituindo o EditValue método para manipular a interface do usuário, processamento de entrada de usuário e atribuição de valor.
Para copiar o código desta explicação passo a passo como uma única lista, consulte Como: criar um controle Windows Forms que tira proveito dos recursos de tempo de Design.
Pré-requisitos
A fim de concluir este explicação passo a passo, será necessário:
- Permissões suficientes para poder criar e executar projetos de aplicativos Windows Forms no computador onde o .NET Framework está instalado.
Definindo um tipo personalizado
Seu editor de tipos de interface do usuário personalizada exibirá um tipo personalizado.Esse tipo pode ser simples ou complexo.Para esta explicação passo a passo, você irá definir um tipo simples com o comportamento de edição de tempo de design personalizado.Esse tipo é chamado de MarqueeLightShape, e é um enum com dois valores, Square e Circle.
Para definir um tipo de enumeração personalizada
No corpo da definição do seu controle Windows Forms, defina a MarqueeLightShape tipo.
' This defines the possible values for the MarqueeBorder ' control's LightShape property. Public Enum MarqueeLightShape Square Circle End Enum
// This defines the possible values for the MarqueeBorder // control's LightShape property. public enum MarqueeLightShape { Square, Circle }
A definição de um controle de exibição
Seu editor de tipos de interface do usuário personalizado exibe a interface de edição usando um controle Windows Forms.Este controle é chamado de LightShapeSelectionControl, e ele deriva de UserControl.Seu construtor usa o valor atual da propriedade e uma referência para o IWindowsFormsEditorService.O controle de exibição usa o CloseDropDown método em IWindowsFormsEditorService para fechar a janela de lista suspensa quando o usuário clica em uma seleção.
Para definir um controle de exibição
No corpo da definição do seu controle Windows Forms, defina a LightShapeSelectionControl controle.
' 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 (components IsNot 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
// This control provides the custom UI for the LightShape property // of the MarqueeBorder. It is used by the LightShapeEditor. public class LightShapeSelectionControl : System.Windows.Forms.UserControl { private MarqueeLightShape lightShapeValue = MarqueeLightShape.Square; private IWindowsFormsEditorService editorService = null; private System.Windows.Forms.Panel squarePanel; private System.Windows.Forms.Panel circlePanel; // Required designer variable. private System.ComponentModel.Container components = null; // This constructor takes a MarqueeLightShape value from the // design-time environment, which will be used to display // the initial state. public LightShapeSelectionControl( MarqueeLightShape lightShape, IWindowsFormsEditorService editorService ) { // This call is required by the designer. InitializeComponent(); // Cache the light shape value provided by the // design-time environment. this.lightShapeValue = lightShape; // Cache the reference to the editor service. this.editorService = editorService; // Handle the Click event for the two panels. this.squarePanel.Click += new EventHandler(squarePanel_Click); this.circlePanel.Click += new EventHandler(circlePanel_Click); } protected override void Dispose( bool disposing ) { if( disposing ) { // Be sure to unhook event handlers // to prevent "lapsed listener" leaks. this.squarePanel.Click -= new EventHandler(squarePanel_Click); this.circlePanel.Click -= new EventHandler(circlePanel_Click); if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } // LightShape is the property for which this control provides // a custom user interface in the Properties window. public MarqueeLightShape LightShape { get { return this.lightShapeValue; } set { if( this.lightShapeValue != value ) { this.lightShapeValue = value; } } } protected override void OnPaint(PaintEventArgs e) { base.OnPaint (e); using( Graphics gSquare = this.squarePanel.CreateGraphics(), gCircle = this.circlePanel.CreateGraphics() ) { // Draw a filled square in the client area of // the squarePanel control. gSquare.FillRectangle( Brushes.Red, 0, 0, this.squarePanel.Width, this.squarePanel.Height ); // If the Square option has been selected, draw a // border inside the squarePanel. if( this.lightShapeValue == MarqueeLightShape.Square ) { gSquare.DrawRectangle( Pens.Black, 0, 0, this.squarePanel.Width-1, this.squarePanel.Height-1); } // Draw a filled circle in the client area of // the circlePanel control. gCircle.Clear( this.circlePanel.BackColor ); gCircle.FillEllipse( Brushes.Blue, 0, 0, this.circlePanel.Width, this.circlePanel.Height ); // If the Circle option has been selected, draw a // border inside the circlePanel. if( this.lightShapeValue == MarqueeLightShape.Circle ) { gCircle.DrawRectangle( Pens.Black, 0, 0, this.circlePanel.Width-1, this.circlePanel.Height-1); } } } private void squarePanel_Click(object sender, EventArgs e) { this.lightShapeValue = MarqueeLightShape.Square; this.Invalidate( false ); this.editorService.CloseDropDown(); } private void circlePanel_Click(object sender, EventArgs e) { this.lightShapeValue = MarqueeLightShape.Circle; this.Invalidate( false ); this.editorService.CloseDropDown(); } #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 void InitializeComponent() { this.squarePanel = new System.Windows.Forms.Panel(); this.circlePanel = new System.Windows.Forms.Panel(); this.SuspendLayout(); // // squarePanel // this.squarePanel.Location = new System.Drawing.Point(8, 10); this.squarePanel.Name = "squarePanel"; this.squarePanel.Size = new System.Drawing.Size(60, 60); this.squarePanel.TabIndex = 2; // // circlePanel // this.circlePanel.Location = new System.Drawing.Point(80, 10); this.circlePanel.Name = "circlePanel"; this.circlePanel.Size = new System.Drawing.Size(60, 60); this.circlePanel.TabIndex = 3; // // LightShapeSelectionControl // this.Controls.Add(this.squarePanel); this.Controls.Add(this.circlePanel); this.Name = "LightShapeSelectionControl"; this.Size = new System.Drawing.Size(150, 80); this.ResumeLayout(false); } #endregion }
Definindo um tipo de interface do usuário Editor classe
Para implementar o comportamento do editor de tipo de interface do usuário, derivam de UITypeEditor classe base.Essa classe é chamada LightShapeEditor.
Para definir um tipo de interface do usuário Editor classe
Permitir o acesso a .NET Framework suporte em tempo de design referenciar o assembly System.Design e importando o System.Drawing.Design e System.Windows.Forms.Design namespaces.Para obter mais informações, consulte Como: suporte de tempo de Design de acesso no Windows Forms.
No corpo da definição do seu controle de formulários de janela, defina a LightShapeEditor classe.
' 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
// 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. internal class LightShapeEditor : UITypeEditor {
Substituindo o método GetEditStyle
O GetEditStyle método indica qual tipo de usuário interface sua implementa de editor de tipo de interface do usuário no ambiente de design.Os valores possíveis são definidos na UITypeEditorEditStyle tipo.O LightShapeEditor implementa uma DropDown editor do tipo de interface do usuário.
Para substituir o método GetEditStyle
No corpo da LightShapeEditor definição, substituir o GetEditStyle método para retornar DropDown.
Public Overrides Function GetEditStyle( _ ByVal context As System.ComponentModel.ITypeDescriptorContext) _ As UITypeEditorEditStyle Return UITypeEditorEditStyle.DropDown End Function
public override UITypeEditorEditStyle GetEditStyle( System.ComponentModel.ITypeDescriptorContext context) { return UITypeEditorEditStyle.DropDown; }
Substituindo o método EditValue
O EditValue método estabelece a interação entre o ambiente de design e a interface do usuário para seu tipo personalizado de edição.O EditValue método cria uma instância do controle de exibição ou com o qual o usuário edita o valor da caixa de diálogo restrita.Quando o usuário termine a edição, o EditValue método retorna o valor para o ambiente de design.
No caso de um controle de exibição como LightShapeSelectionControl, o EditValue método pode passar uma referência para o IWindowsFormsEditorService para o controle de exibição.O controle de exibição pode usar essa referência para fechar a mesmo quando o usuário seleciona um valor.Isso não é necessário para uma caixa de diálogo modal, porque um formulário pode fechar a mesmo.
Para substituir o método EditValue
No corpo da LightShapeEditor definição, substituir o EditValue método.
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)), _ IWindowsFormsEditorService) End If If (editorService IsNot Nothing) Then Dim selectionControl As _ New LightShapeSelectionControl( _ CType(value, MarqueeLightShape), _ editorService) editorService.DropDownControl(selectionControl) value = selectionControl.LightShape End If Return value End Function
public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { if (provider != null) { editorService = provider.GetService( typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService; } if (editorService != null) { LightShapeSelectionControl selectionControl = new LightShapeSelectionControl( (MarqueeLightShape)value, editorService); editorService.DropDownControl(selectionControl); value = selectionControl.LightShape; } return value; }
Substituindo o método PaintValue
Você pode fornecer uma representação gráfica do valor da sua propriedade, substituindo o PaintValue método.
Para substituir o método PaintValue
No corpo da LightShapeEditor definição, substituir o PaintValue método.Também substituir o GetPaintValueSupported método para retornar 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) Else e.Graphics.DrawEllipse(p, e.Bounds) End If End Using End Sub
// This method indicates to the design environment that // the type editor will paint additional content in the // LightShape entry in the PropertyGrid. public override bool GetPaintValueSupported( ITypeDescriptorContext context) { return true; } // This method paints a graphical representation of the // selected value of the LightShpae property. public override void PaintValue(PaintValueEventArgs e) { MarqueeLightShape shape = (MarqueeLightShape)e.Value; using (Pen p = Pens.Black) { if (shape == MarqueeLightShape.Square) { e.Graphics.DrawRectangle(p, e.Bounds); } else { e.Graphics.DrawEllipse(p, e.Bounds); } } }
Anexando o seu Editor de tipos de interface do usuário a uma propriedade
Anexar ao seu editor de tipos de interface do usuário está pronta para uso em seu controle personalizado, o LightShapeEditor para uma propriedade, implementar a propriedade baseada na MarqueeLightShape digite e aplique a EditorAttribute à propriedade.
Para anexar o seu editor de tipos de interface do usuário a uma propriedade
- No corpo da definição do seu controle, declarar um MarqueeLightShape propriedade chamada LightShape.Também declara um campo de instância nomeado lightShapeValue do tipo MarqueeLightShape para a propriedade de volta.Aplicar o EditorAttribute à propriedade.
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;
}
}
Teste o seu Editor de tipos de interface do usuário
Você pode testar o seu editor de tipos de interface do usuário, criando uma instância do seu controle personalizado e anexá-lo para um PropertyGrid controlar usando o SelectedObject propriedade.
Se você estiver usando Visual Studio, crie um novo projeto Windows Application, referência ao assembly do controle e adicione uma instância do seu controle ao formulário.Há suporte abrangente para este recurso no Visual Studio.Para obter mais informações, consulte Demonstra Passo a passo: Populating automaticamente a caixa de ferramentas com Personalizar de componentes e Demonstra Passo a passo: Populating automaticamente a caixa de ferramentas com Personalizar de componentes e Demonstra Passo a passo: Populating automaticamente a caixa de ferramentas com Personalizar de componentes e Demonstra Passo a passo: Preenchendo automaticamente a caixa de ferramentas com componentes personalizados e Demonstra Passo a passo: Preenchendo automaticamente a caixa de ferramentas com componentes personalizados.
Quando as propriedades do controle são exibidas em tempo de design, você pode selecionar o LightShape propriedade.Quando ela é selecionada, uma seta suspensa () é exibida.Quando você clica na seta, seu controle de exibição aparece abaixo da entrada de propriedade.Clique no círculo ou quadrado para selecionar o valor.Após você clicar, o controle de exibição descarta a mesmo e o valor selecionado é exibido na PropertyGrid.
Observação |
---|
Quando você desenvolve seu personalizado UITypeEditor, é recomendável que você defina o número de compilação para incrementar com cada compilação.Isso impede que as versões mais antigas, armazenadas em cache do seu UITypeEditor de ser criado no ambiente de design. |
Próximas etapas
Depois que você tiver criado seu próprio editor de tipos de interface do usuário, explorar outras maneiras de interagir com um PropertyGrid e o ambiente de design:
Escreva um editor UI de tipo com base em uma caixa de diálogo modal, em vez de um controle de exibição.
Escreve um conversor de tipo de um tipo personalizado usando o TypeConverter classe.Para obter mais informações, consulte Como: implementar um conversor de tipo.
Escreva um designer para seu controle personalizado.Para obter mais informações, consulte Como: criar um controle Windows Forms que tira proveito dos recursos de tempo de Design.
Consulte também
Tarefas
Como: criar um controle Windows Forms que tira proveito dos recursos de tempo de Design