Partilhar via


Demonstra Passo a passo: Implementando um editor de tipo de interface do usuário

Você pode fornecer uma experiência de time de design personalizada para tipos de propriedade complexa, Implementando um editor de tipo de interface de 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:

  • Definindo um tipo personalizado.

  • Definir 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 o tipo de editor de estilo que usará o editor.

  • Substituindo o EditValue método para manipular a interface do usuário, processamento de entrada do usuário e atribuição de valor.

Para copiar o código nesta explicação passo a passo sistema autônomo uma única lista, consulte Como: Criar um controle Windows Forms que demora proveito dos recursos de time 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 é 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 comportamento de edição time de design personalizado.Esse tipo é chamado MarqueeLightShape, e é um enum com dois valores Square e Circle.

Para definir um tipo de enumeração personalizado

  • No corpo da definição do controle Windows Forms, definir o MarqueeLightShape Digite.

    ' 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
    }
    

Definição de um controle de exibição

Seu editor de tipos de interface do usuário personalizada exibe a interface de edição usando um controle Windows Forms.Este controle é chamado de LightShapeSelectionControl, e ela deriva de UserControl. O construtor obtém o valor da propriedade corrente e uma referência à 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 controle Windows Forms, definir o 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 de editor de tipo de interface do usuário, derivam o UITypeEditor classe base. Essa classe é chamada LightShapeEditor.

Para definir um tipo de interface do usuário Editor classe

  1. Habilitar o acesso a .NET Framework suporte em time de design referenciando sistema.design do assembly e importando o System.Drawing.Design e System.Windows.Forms.Design espaços para nome. Para obter mais informações, consulte Como: Suporte ao time de design de acesso no Windows Forms.

  2. No corpo da definição do controle Windows Forms, definir o 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

The GetEditStyle método indica para qual tipo de usuário interface sua interface do usuário tipo editor implementa o ambiente de design. Os valores possíveis são definidos no UITypeEditorEditStyle Digite. The LightShapeEditor implementa uma DropDown Editor de tipos de interface do usuário.

Para substituir o método GetEditStyle

  • No corpo do 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

The EditValue método estabelece a interação entre o ambiente de design e a interface do usuário para editar seu tipo personalizado. The EditValue método cria uma instância do controle de exibição ou a caixa de diálogo modal com o qual o usuário edita o valor. Quando o usuário terminar edição, a 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 próprio quando o usuário seleciona um valor.Isso não é necessário para uma caixa de diálogo modal, porque pode fechar um formulário propriamente dito.

Para substituir o método EditValue

  • No corpo do 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 do 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 seu editor de tipo da interface do usuário a uma propriedade

Quando o seu editor de tipos de interface do usuário estiver pronto para uso em seu controle personalizado, anexe o LightShapeEditor uma propriedade, implementar a propriedade com base na MarqueeLightShape Digite e aplique a EditorAttribute a propriedade.

Para anexar o seu editor de tipos de interface do usuário a uma propriedade

  • No corpo da definição do controle, declare um MarqueeLightShape propriedade chamada LightShape. Também declarar um campo instância nomeado lightShapeValue do tipo MarqueeLightShape Para fazer a propriedade. Aplicar o EditorAttribute a 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 seu editor de tipo UI

Você pode testar seu editor de tipos de interface do usuário, criando uma instância do seu controle personalizado e anexá-los a um PropertyGrid controle usando o SelectedObject propriedade.

Se você estiver usando o Visual Studio, criar um novo projeto Windows aplicativo, referência assembly do controle e adicione uma instância do seu controle ao formulário.Há suporte abrangente para este recurso no Visual Studio.

Quando as propriedades do controle são exibidas em time de design, você pode selecionar o LightShape propriedade. Quando ela é selecionada, uma operação de soltar- (seta para baixo) é exibida. Quando você clicar na seta, seu controle de exibição aparece sob a entrada de propriedade.clicar no círculo ou quadrado para selecionar o valor.Após clicar em, descarta o controle de exibição propriamente dito e o valor selecionado é exibido no PropertyGrid.

Observação:

Quando desenvolver seu personalizado UITypeEditor, é recomendável que você defina o número da compilação para incrementar com cada compilação. Isso evita que versões mais antigas, armazenadas em cache do seu UITypeEditor seja criado no ambiente de design.

Próximas etapas

Depois de ter criado seu próprio editor de tipos de interface do usuário, explorar outras maneiras de interagir com um PropertyGrid e o ambiente de criação:

Consulte também

Tarefas

Como: Criar um controle Windows Forms que demora proveito dos recursos de time de design

Referência

UITypeEditor

EditorAttribute

PropertyGrid

Outros recursos

Editores de tipo de interface do usuário