Exemplarische Vorgehensweise: Hinzufügen von Smarttags zu einer Windows Forms-Komponente

Aktualisiert: November 2007

Smarttags sind menüähnliche Elemente der Benutzeroberfläche, die häufig verwendete Entwurfszeitoptionen angeben. Die meisten standardmäßig in .NET Framework bereitgestellten Komponenten und Steuerelemente enthalten Erweiterungen für Smarttags und Designerverben. Die Prozeduren in dieser exemplarischen Vorgehensweise zeigen, wie Komponenten und benutzerdefinierten Steuerelementen die Smarttagunterstützung hinzugefügt wird.

Sie können Windows Forms-Komponenten Smarttags hinzufügen, um häufig verwendete Entwurfszeitoptionen anzugeben. Elemente in einem Smarttagbereich sind logisch nach Kategorie gruppiert, und einzelne DesignerActionMethodItem-Instanzen können optional als Designerverbeinträge dupliziert werden. Viele der standardmäßig in .NET Framework bereitgestellten Komponenten und Steuerelemente enthalten Erweiterungen für Smarttags und Designerverben. Autoren von Komponenten und benutzerdefinierten Steuerelementen können auch Smarttagunterstützung hinzufügen, i. d. R. durch das Verwenden des Pushmodells.

Zum Hinzufügen von Smarttags mit dem Pushmodell sind folgende Zusätze zum Komponentenprojekt erforderlich:

  • Implementierung einer Klasse, abgeleitet von DesignerActionList, um die Methoden und Eigenschaften zu definieren, die Ziele der Smarttagmenüelemente sind. Diese Klasse kann möglicherweise auch eine überschriebene GetSortedActionItems-Methode angeben, die ein Array von DesignerActionItem-Instanzen zurückgibt.

  • Die der Komponente zugeordnete Designerklasse muss die ActionLists-Eigenschaft implementieren. Durch Abrufen dieser Eigenschaft wird die DesignerActionListCollection angegeben, die alle DesignerActionList-Instanzen enthält, die einem einzelnen Smarttagmenü zugeordnet sind. Oft gibt es nur eine Liste in einer solchen Auflistung.

Hinweis:

Im Smarttagbereich wird weder Bildlauf noch Paging unterstützt. Achten Sie also darauf, die Bereiche nicht mit zu vielen Smarttagelementen aufzufüllen. Zu viele Elemente führen möglicherweise dazu, dass sich der Smarttagbereich über die Bildschirmbegrenzung hinaus erstreckt.

Die folgende Prozedur veranschaulicht das Hinzufügen von Smarttags mithilfe von Code aus einem einfachen Beispielsteuerelement, ColorLabel, das von einem standardmäßigen Windows Forms-Label-Steuerelement abgeleitet ist. Dieses Steuerelement verfügt über einen zugeordneten Designer mit dem Namen ColorLabelDesigner.

Informationen, wie Sie in diesem Thema den Code als einzelne Auflistung kopieren können, erhalten Sie unter Gewusst wie: Anfügen von Smarttags an eine Windows Forms-Komponente.

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.

So implementieren Sie eine von DesignerActionList abgeleitete Klasse

  1. Fügen Sie im Namespace der Komponente die Deklaration für die von DesignerActionList abgeleitete Klasse hinzu.

    Public Class ColorLabelActionList
        Inherits System.ComponentModel.Design.DesignerActionList
    
    public class ColorLabelActionList :
              System.ComponentModel.Design.DesignerActionList
    
  2. Fügen Sie dieser Klasse einen Konstruktor hinzu, der eine Instanz des zugeordneten Steuerelements übernimmt. Geben Sie ein privates Feld mit einem Verweis auf diese Instanz an. Geben Sie auch ein privates Feld an, um einen Verweis auf den DesignerActionService zwischenzuspeichern. Dies wird verwendet, um die Liste zu aktualisieren.

    Private colLabel As ColorLabel
    
    
    ...
    
    
    Private designerActionUISvc As DesignerActionUIService = Nothing
    
    
    ...
    
    
    Public Sub New(ByVal component As IComponent)
    
        MyBase.New(component)
        Me.colLabel = component
    
        ' Cache a reference to DesignerActionUIService, so the
        ' DesigneractionList can be refreshed.
        Me.designerActionUISvc = _
        CType(GetService(GetType(DesignerActionUIService)), _
        DesignerActionUIService)
    
    End Sub
    
    private ColorLabel colLabel;
    
    
    ...
    
    
    private DesignerActionUIService designerActionUISvc = null;
    
    
    ...
    
    
    public ColorLabelActionList( IComponent component ) : base(component) 
    {
        this.colLabel = component as ColorLabel;
    
        // Cache a reference to DesignerActionUIService, so the
        // DesigneractionList can be refreshed.
        this.designerActionUISvc =
            GetService(typeof(DesignerActionUIService))
            as DesignerActionUIService;
    }
    
  3. Fügen Sie Methoden und Eigenschaften hinzu, die Sie Smarttagelementen zuordnen möchten. Methoden werden ausgeführt, wenn der entsprechende Smarttageintrag ausgewählt wird. Eigenschaften benötigen Getter-Abschnitte zum Anzeigen der aktuellen Werte. Optional können Eigenschaften auch Setter-Abschnitte enthalten, die die GetProperties-Methode verwenden, wenn die jeweiligen Werte aus dem entsprechenden Smarttageintrag editierbar sein müssen.

    Hinweis:

    In der gesamten Entwurfszeitumgebung kann eine Eigenschaft nur dann bearbeitet werden, wenn einer der Basistypen von .NET Framework bereitgestellt wird. Der Typ kann von einem bereitgestellten TypeConverter oder von einem benutzerdefinierten UITypeEditor in einen Basistyp umgewandelt werden.

    Public Property ForeColor() As Color
        Get
            Return colLabel.ForeColor
        End Get
        Set(ByVal value As Color)
            GetPropertyByName("ForeColor").SetValue(colLabel, value)
        End Set
    End Property
    
    
    ...
    
    
    'Boolean properties are automatically displayed with binary 
    ' UI (such as a checkbox).
    Public Property LockColors() As Boolean
        Get
            Return colLabel.ColorLocked
        End Get
        Set(ByVal value As Boolean)
            GetPropertyByName("ColorLocked").SetValue(colLabel, value)
    
            ' Refresh the list.
            Me.designerActionUISvc.Refresh(Me.Component)
        End Set
    End Property
    
    
    ...
    
    
    Public Sub InvertColors()
        Dim currentBackColor As Color = colLabel.BackColor
        BackColor = Color.FromArgb( _
        255 - currentBackColor.R, _
        255 - currentBackColor.G, _
        255 - currentBackColor.B)
    
        Dim currentForeColor As Color = colLabel.ForeColor
        ForeColor = Color.FromArgb( _
        255 - currentForeColor.R, _
        255 - currentForeColor.G, _
        255 - currentForeColor.B)
    End Sub
    
    public Color ForeColor
    {
        get
        {
            return colLabel.ForeColor;
        }
        set
        {
            GetPropertyByName("ForeColor").SetValue(colLabel, value);
        }
    }
    
    
    ...
    
    
    // Boolean properties are automatically displayed with binary 
    // UI (such as a checkbox).
    public bool LockColors
    {
        get
        {
            return colLabel.ColorLocked;
        }
        set
        {
            GetPropertyByName("ColorLocked").SetValue(colLabel, value);
    
            // Refresh the list.
            this.designerActionUISvc.Refresh(this.Component);
        }
    }
    
    
    ...
    
    
    public void InvertColors()
    {
        Color currentBackColor = colLabel.BackColor;
        BackColor = Color.FromArgb(
            255 - currentBackColor.R, 
            255 - currentBackColor.G, 
            255 - currentBackColor.B);
    
        Color currentForeColor = colLabel.ForeColor;
        ForeColor = Color.FromArgb(
            255 - currentForeColor.R, 
            255 - currentForeColor.G, 
            255 - currentForeColor.B);
    }
    
  4. Optional können Sie eine überschriebene Version der GetSortedActionItems-Methode implementieren, um ein Array von DesignerActionItem-Instanzen zurückzugeben, wobei jedes Element einer im vorherigen Schritt erstellten Eigenschaft oder Methode zugeordnet ist. Auf diese Weise können Sie die Reihenfolge der Elemente ändern, diese kategorisieren oder optional anzeigen. Die Liste kann auch statische Elemente einschließen, z. B. logische Gruppentitel.

    Public Overrides Function GetSortedActionItems() _
    As DesignerActionItemCollection
        Dim items As New DesignerActionItemCollection()
    
        'Define static section header entries.
        items.Add(New DesignerActionHeaderItem("Appearance"))
        items.Add(New DesignerActionHeaderItem("Information"))
    
        'Boolean property for locking color selections.
        items.Add(New DesignerActionPropertyItem( _
        "LockColors", _
        "Lock Colors", _
        "Appearance", _
        "Locks the color properties."))
    
        If Not LockColors Then
            items.Add( _
            New DesignerActionPropertyItem( _
            "BackColor", _
            "Back Color", _
            "Appearance", _
            "Selects the background color."))
    
            items.Add( _
            New DesignerActionPropertyItem( _
            "ForeColor", _
            "Fore Color", _
            "Appearance", _
            "Selects the foreground color."))
    
            'This next method item is also added to the context menu 
            ' (as a designer verb).
            items.Add( _
            New DesignerActionMethodItem( _
            Me, _
            "InvertColors", _
            "Invert Colors", _
            "Appearance", _
            "Inverts the fore and background colors.", _
            True))
        End If
        items.Add( _
        New DesignerActionPropertyItem( _
        "Text", _
        "Text String", _
        "Appearance", _
        "Sets the display text."))
    
        'Create entries for static Information section.
        Dim location As New StringBuilder("Location: ")
        location.Append(colLabel.Location)
        Dim size As New StringBuilder("Size: ")
        size.Append(colLabel.Size)
    
        items.Add( _
        New DesignerActionTextItem( _
        location.ToString(), _
        "Information"))
    
        items.Add( _
        New DesignerActionTextItem( _
        size.ToString(), _
        "Information"))
    
        Return items
    End Function
    
    public override DesignerActionItemCollection GetSortedActionItems()
    {
        DesignerActionItemCollection items = new DesignerActionItemCollection();
    
        //Define static section header entries.
        items.Add(new DesignerActionHeaderItem("Appearance"));
        items.Add(new DesignerActionHeaderItem("Information"));
    
        //Boolean property for locking color selections.
        items.Add(new DesignerActionPropertyItem("LockColors",
                         "Lock Colors", "Appearance",
                         "Locks the color properties."));
        if (!LockColors)
        {
            items.Add(new DesignerActionPropertyItem("BackColor",
                             "Back Color", "Appearance",
                             "Selects the background color."));
            items.Add(new DesignerActionPropertyItem("ForeColor",
                             "Fore Color", "Appearance",
                             "Selects the foreground color."));
    
            //This next method item is also added to the context menu 
            // (as a designer verb).
            items.Add(new DesignerActionMethodItem(this,
                             "InvertColors", "Invert Colors",
                             "Appearance",
                             "Inverts the fore and background colors.",
                              true));
        }
        items.Add(new DesignerActionPropertyItem("Text",
                         "Text String", "Appearance",
                         "Sets the display text."));
    
        //Create entries for static Information section.
        StringBuilder location = new StringBuilder("Location: ");
        location.Append(colLabel.Location);
        StringBuilder size = new StringBuilder("Size: ");
        size.Append(colLabel.Size);
        items.Add(new DesignerActionTextItem(location.ToString(),
                         "Information"));
        items.Add(new DesignerActionTextItem(size.ToString(),
                         "Information"));
    
        return items;
    }
    

So aktualisieren Sie die zugeordnete Designerklasse, um die ActionLists-Eigenschaft zu implementieren

  1. Suchen Sie die Designerklasse für das Steuerelement. Wenn keine vorhanden ist, erstellen Sie eine Designerklasse, und ordnen Sie diese der Steuerelementklasse zu. Weitere Informationen zu Designern finden Sie unter Basisklassen für Designer.

  2. Fügen Sie zur Optimierung ein privates Feld des Typs DesignerActionListCollection hinzu.

    Private lists As DesignerActionListCollection
    
    private DesignerActionListCollection actionLists;
    
  3. Fügen Sie die überschriebene ActionLists-Eigenschaft hinzu, um eine neue Instanz der zuvor erstellten ColorLabelActionList-Klasse zurückzugeben.

    Public Overrides ReadOnly Property ActionLists() _
    As DesignerActionListCollection
        Get
            If lists Is Nothing Then
                lists = New DesignerActionListCollection()
                lists.Add( _
                New ColorLabelActionList(Me.Component))
            End If
            Return lists
        End Get
    End Property
    
    public override DesignerActionListCollection ActionLists
    {
        get
        {
            if (null == actionLists)
            {
                actionLists = new DesignerActionListCollection();
                actionLists.Add(
                    new ColorLabelActionList(this.Component));
            }
            return actionLists;
        }
    }
    

Anmerkungen

Mehrere Bereiche des Codes bedürfen einer ausführlicheren Erklärung:

  • Wenn eine Eigenschaft oder Methode in der von DesignerActionList abgeleiteten Klasse den Zustand des zugeordneten Steuerelements ändert, dürfen diese Änderungen nicht durch direkte Setter-Aufrufe der Eigenschaften der Komponente erfolgen. Stattdessen müssen solche Änderungen von einem entsprechend erstellten PropertyDescriptor vorgenommen werden. Durch diesen indirekten Ansatz wird sichergestellt, dass Smarttagaktionen korrekt rückgängig gemacht und Benutzeroberflächenaktualisierungen korrekt ausgeführt werden können.

  • Sie können den Smarttagbereich dynamisch aktualisieren, indem Sie DesignerActionUIService.Refresh aufrufen. Dieser Prozess kann verwendet werden, um den Inhalt des Smarttagbereichs dynamisch zu ändern. Im Beispiel werden die Smarttags zum Ändern von Farben konditional in Abhängigkeit vom Zustand der LockColors-Eigenschaft eingeschlossen. Diese boolesche Eigenschaft ist auch einem Smarttag zugeordnet, sodass der Entwickler die aktuelle Farbauswahl zumindest über das Menü sperren und entsperren kann.

  • Ein Smarttageintrag vom Typ DesignerActionMethodItem kann optional in das Kontextmenü des zugeordneten Steuerelements aufgenommen werden, indem Sie den includeAsDesignerVerb-Parameter im Konstruktor auf true festlegen. .NET Framework erstellt dann implizit ein entsprechendes DesignerVerb und fügt es für Sie dem Kontextmenü hinzu. In diesem Beispiel wird das InvertColors-Element auf diese Weise behandelt.

  • Smarttagelemente werden in einem Bereich nach der jeweiligen Category-Eigenschaft gruppiert, die im Konstruktor für jedes Element festgelegt ist. Wenn diese Eigenschaft nicht explizit festgelegt ist, wird sie der Standardkategorie zugewiesen. Alle Elemente im Smarttagbereich werden nach Kategorie und dann nach der Reihenfolge ihres Auftretens im DesignerActionItem-Array sortiert, das von der aus der DesignerActionList-Klasse abgeleiteten Klasse zurückgegeben wird. Dieses Beispiel enthält zwei Kategorien: Appearance und Information.

    Hinweis:

    Für die zweite Kategorie wird kein DesignerActionHeaderItem bereitgestellt.

  • Ein Eintrag, der statische Textinformationen anzeigt, kann entweder mithilfe eines DesignerActionTextItem oder mithilfe eines DesignerActionPropertyItem implementiert werden, dessen zugeordnete Eigenschaft nur einen Setter enthält. In diesem Beispiel wird der erste Ansatz verwendet.

Nächste Schritte

Wenn Sie die Komponente in die Entwurfszeitumgebung integrieren, können Sie auch die entsprechende Designerunterstützung erweitern.

Siehe auch

Konzepte

Designerbefehle und das DesignerAction-Objektmodell für Windows Forms

Referenz

DesignerVerb

DesignerActionItem

DesignerActionList

ActionLists

DesignerActionService