Condividi tramite


Procedura dettagliata: aggiunta di smart tag a un componente Windows Form

Gli smart tag sono elementi dell'interfaccia utente simili a menu che forniscono opzioni di progettazione di utilizzo frequente. La maggior parte dei controlli e dei componenti standard forniti con .NET Framework contiene miglioramenti relativi ai verbi di progettazione e agli smart tag. Nella presente procedura dettagliata viene illustrato come aggiungere il supporto per gli smart tag a componenti e controlli personalizzati.

È possibile aggiungere smart tag ai componenti Window Form per fornire le opzioni di progettazione di uso comune. Gli elementi di un pannello smart tag sono raggruppati logicamente per categoria, mentre le singole istanze di DesignerActionMethodItem possono essere facoltativamente duplicate come voci di verbi di progettazione. Molti controlli e componenti standard forniti con .NET Framework contengono miglioramenti relativi ai verbi di progettazione e agli smart tag. Gli autori di componenti e controlli personalizzati possono inoltre aggiungere il supporto smart tag, solitamente utilizzando il modello push.

L'aggiunta di smart tag mediante il modello push richiede le seguenti aggiunte al progetto del componente:

  • Implementazione di una classe derivata da DesignerActionList che definisce i metodi e le proprietà come destinazioni delle voci di menu smart tag. La classe può fornire inoltre un metodo GetSortedActionItems sottoposto a override che restituisce una matrice di istanze DesignerActionItem.

  • La classe di finestre di progettazione associata al componente deve implementare la proprietà ActionLists. Recuperando questa proprietà si fornisce la classe DesignerActionListCollection che contiene tutte le istanze di DesignerActionList associate a un solo menu smart tag. Spesso in tale insieme è presente un solo elenco.

Nota

Poiché i pannelli smart tag non supportano lo scorrimento o il paging, non inserire un numero eccessivo di elementi smart tag, altrimenti si rischia che il pannello smart tag si estenda oltre il limite dello schermo.

Nella procedura riportata di seguito viene illustrato come aggiungere smart tag mediante codice da un semplice controllo di esempio, ColorLabel, derivato dal controllo Label standard di Windows Form. A tale controllo è associata una finestra di progettazione denominata ColorLabelDesigner.

Per copiare il codice contenuto in questo argomento come elenco singolo, vedere Procedura: collegare smart tag a un componente Windows Form.

Prerequisiti

Per completare questa procedura dettagliata, è necessario disporre dei seguenti elementi:

  • Disporre di autorizzazioni sufficienti per la creazione e l'esecuzione di progetti dell'applicazione Windows Form nel computer in cui è installato .NET Framework.

Per implementare una classe derivata da DesignerActionList

  1. Nello stesso spazio dei nomi del componente, aggiungere la dichiarazione relativa alla classe derivata da DesignerActionList.

    Nota

    È necessario aggiungere un riferimento all'assembly della fase di progettazione, System.Design.dll. Questo assembly non è incluso in .NET Framework 4 Client Profile. Per aggiungere un riferimento a System.Design.dll, è necessario modificare il framework di destinazione del progetto in .NET Framework 4.

    Public Class ColorLabelActionList
        Inherits System.ComponentModel.Design.DesignerActionList
    
    public class ColorLabelActionList :
              System.ComponentModel.Design.DesignerActionList
    
  2. Aggiungere un costruttore a tale classe che accetti un'istanza del controllo associato. Fornire un campo privato che contenga un riferimento all'istanza. Fornire inoltre un campo privato per la memorizzazione nella cache di un riferimento alla classe DesignerActionService che verrà utilizzato per aggiornare l'elenco.

    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. Aggiungere metodi e proprietà che si desidera associare agli elementi smart tag. I metodi verranno eseguiti alla selezione della voce smart tag corrispondente. Le proprietà devono disporre di sezioni Get in modo che venga visualizzato il relativo valore corrente; facoltativamente, possono presentare sezioni Set che utilizzano il metodo GetProperties e i relativi valori devono essere modificabili dalla voce smart tag corrispondente.

    Nota

    Come accade nell'ambiente di progettazione, una proprietà può essere modificata unicamente se uno solo dei tipi base viene fornito da .NET Framework, se il tipo può essere convertito in un tipo base da una classe TypeConverter fornita oppure quando viene fornita una classe UITypeEditor personalizzata.

    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. Implementare facoltativamente una versione sottoposta a override del metodo GetSortedActionItems per restituire una matrice di istanze DesignerActionItem, in cui ciascun elemento è associato a una proprietà o un metodo creato nel passaggio precedente. L'operazione consente di modificare l'ordine degli elementi, suddividerli in categorie o facoltativamente visualizzarli. L'elenco può anche includere elementi statici quali titoli di gruppi logici.

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

Per aggiornare la classe di progettazione associata in modo da implementare la proprietà ActionLists

  1. Individuare la classe di finestre di progettazione relativa al controllo. Se non ne esiste alcuna, creare una classe di finestre di progettazione e associarla alla classe del controllo. Per ulteriori informazioni sulle finestre di progettazione, vedere Classi base della finestra di progettazione.

  2. Come tecnica di ottimizzazione aggiungere un campo privato di tipo DesignerActionListCollection.

    Private lists As DesignerActionListCollection
    
    private DesignerActionListCollection actionLists;
    
  3. Aggiungere la proprietà ActionLists sottoposta a ovveride per restituire una nuova istanza della classe ColorLabelActionList creata in precedenza.

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

Commenti

Per diverse aree di codice sono necessarie informazioni più dettagliate:

  • Quando per una proprietà o un metodo della classe derivata da DesignerActionList viene modificato lo stato del controllo associato, tali modifiche non dovrebbero essere apportate da chiamate dirette del metodo per l'impostazione alle proprietà del componente. Piuttosto, tali modifiche dovrebbero essere apportate tramite una classe PropertyDescriptor appositamente creata. Tale approccio indiretto garantisce il corretto funzionamento dell'annullamento degli smart tag e delle azioni di aggiornamento dell'interfaccia utente.

  • Per aggiornare dinamicamente il pannello smart tag, è possibile chiamare il metodo DesignerActionUIService.Refresh. Tale processo consente di modificare dinamicamente il contenuto del pannello smart tag. Nell'esempio gli smart tag coinvolti nella modifica dei colori sono inclusi in maniera condizionale, in base allo stato della proprietà LockColors. Tale proprietà booleana è inoltre associata a uno smart tag, in modo che lo sviluppatore sia in grado di bloccare o sbloccare la selezione di colori corrente, almeno attraverso il menu.

  • Facoltativamente, una voce smart tag di tipo DesignerActionMethodItem può essere inclusa nel menu di scelta rapida per il controllo associato mediante l'impostazione del parametro includeAsDesignerVerb del costruttore su true. In .NET Framework viene quindi creato implicitamente un oggetto DesignerVerb che viene aggiunto al menu di scelta rapida. In questo esempio l'elemento InvertColors viene considerato nel modo suddetto.

  • Gli elementi smart tag vengono raggruppati in un pannello in base alla rispettiva proprietà Category, impostata nel costruttore per ciascun elemento. Se la proprietà non è impostata esplicitamente, viene assegnata alla categoria predefinita. Ciascun elemento viene ordinato nel pannello smart tag per categoria, quindi per ordine di occorrenza nella matrice DesignerActionItem restituita dalla classe derivata da DesignerActionList. Nell'esempio di seguito sono incluse due categorie: Appearance e Information.

    Nota

    Per la seconda categoria non viene fornito alcun oggetto DesignerActionHeaderItem.

  • Una voce che consente di visualizzare informazioni di testo statico può essere implementata utilizzando un oggetto DesignerActionTextItem o DesignerActionPropertyItem la cui proprietà associata contenga un solo metodo per l'impostazione. Nell'esempio viene utilizzato il primo approccio.

Passaggi successivi

Dopo aver avviato l'integrazione del componente nell'ambiente di progettazione, valutare la possibilità di espanderne il supporto della finestra di progettazione.

Vedere anche

Riferimenti

DesignerVerb

DesignerActionItem

DesignerActionList

ActionLists

DesignerActionService

Concetti

Comandi della finestra di progettazione e modello a oggetti DesignerAction per Windows Form