Exemplarische Vorgehensweise: Implementieren eines Typ-Editors für die Benutzeroberfläche

Aktualisiert: November 2007

Durch das Implementieren eines Typ-Editors für die Benutzeroberfläche können Sie für komplexe Eigenschaftentypen eine benutzerdefinierte Entwurfszeitausführung bereitstellen.

Anhand dieser exemplarischen Vorgehensweise wird erläutert, wie Sie für einen benutzerdefinierten Typ Ihren eigenen Typ-Editor für die Benutzeroberfläche erstellen und wie Sie die Bearbeitungsschnittstelle mithilfe eines PropertyGrid anzeigen können.

In dieser exemplarischen Vorgehensweise werden folgende Aufgaben erläutert:

  • Definieren eines benutzerdefinierten Typs

  • Definieren eines Ansichtssteuerelements für den Typ-Editor für die Benutzeroberfläche

  • Definieren einer Klasse, die von UITypeEditor abgeleitet ist

  • Überschreiben der GetEditStyle-Methode, um dem PropertyGrid mitzuteilen, welchen Editorstil der Editor verwendet

  • Überschreiben der EditValue-Methode für die Behandlung der Benutzeroberfläche, die Verarbeitung von Benutzereingaben und die Zuweisung von Werten

Informationen dazu, wie der Code in dieser exemplarischen Vorgehensweise als Einzelauflistung kopiert werden kann, finden Sie unter Gewusst wie: Erstellen eines Windows Forms-Steuerelements, das Entwurfszeitfeatures nutzt.

Vorbereitungsmaßnahmen

Für die Durchführung dieser exemplarischen Vorgehensweise benötigen Sie Folgendes:

  • Ausreichende Berechtigungen zum Erstellen und Ausführen von Windows Forms-Anwendungsprojekten auf dem Computer, auf dem .NET Framework installiert ist

Definieren eines benutzerdefinierten Typs

Der Typ-Editor für die benutzerdefinierte Benutzeroberfläche zeigt einen benutzerdefinierten Typ an. Es kann sich dabei um einen komplexen oder einen einfachen Typ handeln. In dieser exemplarischen Vorgehensweise definieren Sie einen einfachen Typ mit benutzerdefiniertem Bearbeitungsverhalten zur Entwurfszeit. Dieser Typ wird mit MarqueeLightShape bezeichnet und ist ein enum mit zwei Werten, Square und Circle.

So definieren Sie einen benutzerdefinierten Enumerationstyp

  • Definieren Sie im Text der Definition des Windows Forms-Steuerelements den MarqueeLightShape-Typ.

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

Definieren eines Ansichtssteuerelements

Der Typ-Editor für die benutzerdefinierte Benutzeroberfläche zeigt die Bearbeitungsschnittstelle mit einem Windows Forms-Steuerelement an. Dieses Steuerelement wird mit LightShapeSelectionControl bezeichnet und von UserControl abgeleitet. Sein Konstruktor übernimmt den aktuellen Eigenschaftenwert und einen Verweis auf den IWindowsFormsEditorService. Das Ansichtssteuerelement verwendet die CloseDropDown-Methode für IWindowsFormsEditorService, um das Dropdownfenster zu schließen, wenn der Benutzer auf eine Auswahl klickt.

So definieren Sie ein Ansichtssteuerelement

  • Definieren Sie im Text der Definition des Windows Forms-Steuerelements das LightShapeSelectionControl-Steuerelement.

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

Definieren einer Klasse für den Typ-Editor für die Benutzeroberfläche

Um das Verhalten des Typ-Editors für die Benutzeroberfläche zu implementieren, leiten Sie von der UITypeEditor-Basisklasse ab. Diese Klasse wird mit LightShapeEditor bezeichnet.

So definieren Sie eine Klasse für den Typ-Editor für die Benutzeroberfläche

  1. Aktivieren Sie den Zugriff auf die Entwurfszeitunterstützung für .NET Framework, indem Sie auf die System.Design-Assembly verweisen und den System.Drawing.Design-Namespace sowie den System.Windows.Forms.Design-Namespace importieren. Weitere Informationen finden Sie unter Gewusst wie: Zugriff auf Entwurfszeitunterstützung in Windows Forms.

  2. Definieren Sie im Text der Definition des Windows Forms-Steuerelements die LightShapeEditor-Klasse.

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

Überschreiben der GetEditStyle-Methode

Die GetEditStyle-Methode zeigt der Entwurfsumgebung an, welche Art von Benutzeroberfläche der Typ-Editor für die Benutzeroberfläche implementiert. Die möglichen Werte werden im UITypeEditorEditStyle-Typ definiert. Der LightShapeEditor implementiert einen DropDown-Typ-Editor für die Benutzeroberfläche.

So überschreiben Sie die GetEditStyle-Methode

  • Überschreiben Sie im Text der LightShapeEditor-Definition die GetEditStyle-Methode, damit DropDown zurückgegeben wird.

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

Überschreiben der EditValue-Methode

Die EditValue-Methode stellt die Interaktion zwischen der Entwurfsumgebung und der Benutzeroberfläche für die Bearbeitung des benutzerdefinierten Typs her. Mit der EditValue-Methode wird eine Instanz des Ansichtssteuerelements oder des modalen Dialogfelds erstellt, über das der Benutzer den Wert bearbeitet. Wenn die Bearbeitung durch den Benutzer abgeschlossen ist, gibt die EditValue-Methode den Wert an die Entwurfsumgebung zurück.

Wenn es sich um ein Ansichtssteuerelement, z. B. LightShapeSelectionControl, handelt, übergibt die EditValue-Methode möglicherweise einen Verweis auf den IWindowsFormsEditorService an das Ansichtssteuerelement. Mithilfe des Verweises kann sich das Ansichtssteuerelement beenden, wenn der Benutzer einen Wert auswählt. Im Fall eines modalen Dialogfelds ist dies nicht erforderlich, da sich Formulare selbsttätig beenden können.

So überschreiben Sie die EditValue-Methode

  • Überschreiben Sie im Text der LightShapeEditor-Definition die EditValue-Methode.

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

Überschreiben der PaintValue-Methode

Durch das Überschreiben der PaintValue-Methode können Sie eine grafische Darstellung des Werts der Eigenschaft bereitstellen.

So überschreiben Sie die PaintValue-Methode

  • Überschreiben Sie im Text der LightShapeEditor-Definition die PaintValue-Methode. Überschreiben Sie auch die GetPaintValueSupported-Methode, damit true zurückgegeben wird.

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

Anfügen des Typ-Editors für die Benutzeroberfläche an eine Eigenschaft

Sobald der Typ-Editor für die Benutzeroberfläche zur Verwendung im benutzerdefinierten Steuerelement bereit ist, fügen Sie LightShapeEditor an eine Eigenschaft an, implementieren Sie die auf dem MarqueeLightShape-Typ basierende Eigenschaft, und wenden Sie das EditorAttribute auf die Eigenschaft an.

So fügen Sie den Typ-Editor für die Benutzeroberfläche an eine Eigenschaft an

  • Deklarieren Sie im Text der Definition des Steuerelements eine MarqueeLightShape-Eigenschaft mit dem Namen LightShape. Deklarieren Sie zur Unterstützung der Eigenschaft auch ein Instanzfeld des Typs MarqueeLightShape mit dem Namen lightShapeValue. Wenden Sie das EditorAttribute auf die Eigenschaft an.
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;
    }
}

Testen des Typ-Editors für die Benutzeroberfläche

Sie können den Typ-Editor für die Benutzeroberfläche testen, indem Sie eine Instanz des benutzerdefinierten Steuerelements erstellen und diese mithilfe der SelectedObject-Eigenschaft einem PropertyGrid-Steuerelement hinzufügen.

Bei Verwendung von Visual Studio können Sie ein neues Windows-Anwendungsprojekt erstellen, auf die Assembly des Steuerelements verweisen und dem Formular eine Instanz des Steuerelements hinzufügen. Für diese Aufgabe wird in Visual Studio umfassende Unterstützung angeboten.

Wenn die Eigenschaften für das Steuerelement zur Entwurfszeit angezeigt werden, können Sie die LightShape-Eigenschaft auswählen. Bei Auswahl der Eigenschaft wird ein Dropdownpfeil () angezeigt. Wenn Sie auf den Pfeil klicken, wird das Ansichtssteuerelement unterhalb des Eigenschafteneintrags angezeigt. Klicken Sie auf den Kreis oder das Quadrat, um den Wert auszuwählen. Nach der Auswahl des Werts schließt sich das Ansichtssteuerelement selbsttätig, und der ausgewählte Wert wird im PropertyGrid angezeigt.

Hinweis:

Wenn Sie einen benutzerdefinierten UITypeEditor entwickeln, ist es ratsam, die Buildnummer so zu konfigurieren, dass sie mit jedem Build erhöht wird. Dadurch wird verhindert, dass in der Entwicklungsumgebung ältere, zwischengespeicherte Versionen von UITypeEditor erstellt werden.

Nächste Schritte

Nachdem Sie einen eigenen UI-Typ-Editor erstellt haben, können Sie weitere Möglichkeiten der Interaktion mit PropertyGrid und der Entwurfsumgebung untersuchen:

Siehe auch

Aufgaben

Gewusst wie: Erstellen eines Windows Forms-Steuerelements, das Entwurfszeitfeatures nutzt

Referenz

UITypeEditor

EditorAttribute

PropertyGrid

Weitere Ressourcen

UI-Typ-Editoren