Partager via


Procédure pas à pas : ajout de balises actives à un composant Windows Forms

Les balises actives sont des éléments d'interface utilisateur de type menu qui fournissent des options fréquemment utilisées au moment du design. La plupart des composants et contrôles standard fournis avec le .NET Framework contiennent des améliorations concernant les balises actives et les verbes du concepteur. Les opérations de cette procédure pas à pas vous montrent comment ajouter la prise en charge de balises actives aux composants et aux contrôles personnalisés.

Vous pouvez ajouter des balises actives aux composants Windows Forms pour fournir des options fréquemment utilisées au moment du design. Les éléments d'un panneau des balises actives sont regroupés logiquement par catégorie, et les instances DesignerActionMethodItem individuelles peuvent éventuellement être dupliquées comme entrées de verbe du concepteur. De nombreux composants et contrôles standard fournis avec le .NET Framework contiennent des améliorations concernant les balises actives et les verbes du concepteur. Les auteurs de composants et de contrôles personnalisés peuvent également ajouter la prise en charge de balises actives, en utilisant généralement le modèle push.

L'ajout de balises actives avec le modèle push requiert les ajouts suivants au projet de composant :

  • Implémentation d'une classe, dérivée de DesignerActionList, qui définit les méthodes et propriétés qui sont les cibles des éléments du menu de balises actives. Cette classe peut également fournir une méthode GetSortedActionItems substituée qui retourne un tableau d'instances de DesignerActionItem.

  • La classe du concepteur associée au composant doit implémenter la propriété ActionLists. La récupération de cette propriété fournit la DesignerActionListCollection qui contient toutes les instances DesignerActionList associées à un seul menu de balises actives. Souvent, il n'existe qu'une seule liste dans ce type de collection.

Notes

Les panneaux de balises actives ne prennent pas en charge le défilement ou la pagination ; veillez donc à ne pas remplir vos panneaux avec de nombreux éléments de balise active.Trop d'éléments peuvent provoquer l'extension du panneau des balises actives au-delà de la limite d'écran.

La procédure suivante montre comment ajouter des balises actives à l'aide du code d'un exemple de contrôle simple, ColorLabel, qui est dérivé du contrôle Label Windows Forms standard. Ce contrôle possède un concepteur associé nommé ColorLabelDesigner.

Pour copier le code dans cette rubrique sous forme de liste unique, consultez Comment : attacher des balises actives à un composant Windows Forms.

Composants requis

Pour exécuter cette procédure pas à pas, vous devez disposer des composants suivants :

  • disposer d'autorisations suffisantes pour pouvoir créer et exécuter des projets d'application Windows Forms sur l'ordinateur où le .NET Framework est installé.

Pour implémenter une classe dérivée de DesignerActionList

  1. Dans le même espace de noms que celui de votre composant, ajoutez la déclaration pour votre classe dérivée de DesignerActionList.

    Notes

    Vous devez ajouter une référence à l'assembly au moment du design, System.Design.dll.Cet assembly n'est pas inclus dans le Framework 4 Client Profile.Pour ajouter une référence à System.Design.dll, vous devez remplacer le Framework cible du projet par .NET Framework 4.

    Public Class ColorLabelActionList
        Inherits System.ComponentModel.Design.DesignerActionList
    
    public class ColorLabelActionList :
              System.ComponentModel.Design.DesignerActionList
    
  2. Ajoutez à cette classe un constructeur qui accepte une instance du contrôle associé. Fournissez un champ privé pour contenir une référence à cette instance. Fournissez également un champ privé pour mettre en cache une référence au DesignerActionService. Il sera utilisé pour mettre à jour la liste.

    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. Ajoutez les méthodes et les propriétés que vous souhaitez associer aux éléments de balise active. Les méthodes sont exécutées lorsque leur entrée de balise active correspondante est sélectionnée. Les propriétés doivent disposer de sections d'accesseur Get pour que leur valeur actuelle soit affichée. Elles peuvent éventuellement disposer de sections d'accesseur Set qui utilisent la méthode GetProperties si leurs valeurs sont modifiables à partir de l'entrée de balise active correspondante.

    Notes

    Comme c'est le cas dans tout l'environnement au moment du design, une propriété peut être modifiée uniquement si l'un des types de base est fourni par le .NET Framework, si le type peut être converti en type de base par un TypeConverter fourni ou lorsqu'un UITypeEditor personnalisé est fourni.

    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. Implémentez éventuellement une version substituée de la méthode GetSortedActionItems pour retourner un tableau d'instances DesignerActionItem dans lequel chaque élément est associé à une propriété ou une méthode créée à l'étape précédente. Vous pouvez exécuter cette opération pour modifier l'ordre des éléments, les classer ou éventuellement les afficher. La liste peut également inclure des éléments statiques tels que les titres de groupes logiques.

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

Pour mettre à jour la classe de concepteur associée afin d'implémenter la propriété ActionLists

  1. Localisez la classe de concepteur pour le contrôle. S'il n'en existe pas, créez une classe de concepteur et associez-la à la classe de contrôle. Pour plus d'informations sur les concepteurs, consultez Classes de concepteurs de base.

  2. Comme technique d'optimisation, ajoutez un champ privé de type DesignerActionListCollection.

    Private lists As DesignerActionListCollection
    
    private DesignerActionListCollection actionLists;
    
  3. Ajoutez la propriété ActionLists substituée pour retourner une nouvelle instance de la classe ColorLabelActionList que vous avez créée précédemment.

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

Commentaires

Certaines parties du code méritent une explication plus détaillée :

  • Lorsqu'une propriété ou une méthode dans la classe dérivée de DesignerActionList modifie l'état du contrôle associé, ces modifications ne doivent pas être effectuées par des appels d'accesseur Set directs aux propriétés du composant. Ces modifications doivent plutôt être effectuées par le biais d'un PropertyDescriptor créé de manière appropriée. Cette approche indirecte garantit que les opérations d'annulation de balise active et de mise à jour de l'interface utilisateur s'exécutent correctement.

  • Vous pouvez mettre à jour dynamiquement le panneau des balises actives en appelant DesignerActionUIService.Refresh. Ce processus peut être utilisé pour modifier dynamiquement le contenu du panneau des balises actives. Dans l'exemple, les balises actives concernées par la modification des couleurs sont incluses de manière conditionnelle selon l'état de la propriété LockColors. Cette propriété booléenne est également associée à une balise active, de sorte que le développeur peut verrouiller ou déverrouiller la sélection de couleurs actuelle, au moins par le menu.

  • Une entrée de balise active de type DesignerActionMethodItem peut éventuellement être incluse dans le menu contextuel pour le contrôle associé en affectant au paramètre includeAsDesignerVerb la valeur true dans le constructeur. Le .NET Framework crée alors implicitement un DesignerVerb correspondant, puis l'ajoute au menu contextuel. Dans cet exemple, l'élément InvertColors est traité de cette manière.

  • Les éléments de balise active sont regroupés dans un panneau par leur propriété Category, qui est définie dans le constructeur pour chaque élément. Si cette propriété n'est pas explicitement définie, elle est assignée à la catégorie par défaut. Chaque élément est classé dans le panneau des balises actives par catégorie, puis par ordre d'occurrence dans le tableau DesignerActionItem retourné par la classe dérivée de la classe DesignerActionList. Cet exemple met en jeu deux catégories : Appearance et Information.

    Notes

    Aucun DesignerActionHeaderItem n'est fourni pour la deuxième catégorie.

  • Une entrée qui affiche des informations textuelles statiques peut être implémentée à l'aide d'un DesignerActionTextItem ou d'un DesignerActionPropertyItem dont la propriété associée contient uniquement un accesseur Set. Cet exemple utilise la première approche.

Étapes suivantes

Une fois que vous avez commencé à intégrer votre composant dans l'environnement au moment du design, envisagez de développer sa prise en charge de concepteur.

Voir aussi

Référence

DesignerVerb

DesignerActionItem

DesignerActionList

ActionLists

DesignerActionService

Concepts

Commandes du concepteur et modèle objet DesignerAction pour les Windows Forms