Partilhar via


Demonstra Passo a passo: Criando um MenuAction

Essa explicação passo a passo mostra como criar um adorno em tempo de design de um controle personalizado Windows Presentation Foundation (WPF).You can use this shortcut menu item to set the value of the Background property on a custom button control.Para obter uma lista completa de código, consulte Como: Criar um MenuAction.

Nesta explicação passo a passo, você executa as seguintes tarefas:

  • Criar um projeto de biblioteca de controle personalizado WPF .

  • Criar um conjunto de módulos (assembly) separado de metadados em tempo de design.

  • Implemente o provedor menu.

  • Testar o controle em tempo de design.

Quando você terminar, você saberá como criar um provedor de adorno para um controle personalizado.

Observação:

As caixas de diálogo e comandos de menu demonstradas podem ser diferentes daqueles descritas na Ajuda, dependendo das configurações ativas ou configurações de edição.Para alterar as configurações, escolher Importar e exportar configurações on the Ferramentas menu.Para obter mais informações, consulte Configurações do Visual Studio.

Pré-requisitos

Para completar este passo a passo, são necessários os seguintes componentes:

  • Visual Studio 2008.

Criando o Controle Personalizado

A primeira etapa é criar o projeto para o controle personalizado.O controle é um botão simples com pequena quantidade de código em tempo de design, que usa o método GetIsInDesignMode para implementar um comportamento de tempo de design.

Para criar o controle personalizado

  1. Crie um novo projeto da biblioteca de controle personalizado WPF no Visual C# denominado CustomControlLibrary.

    O código de CustomControl1 abre no Editor de Códigos.

  2. In O gerenciador de soluções, altere o nome do arquivo de código para ButtonWithDesignTime.cs ou ButtonWithDesignTime.vb.Se um caixa de mensagem aparecer que pergunta se você deseja executar uma renomeação para todas as referências no projeto atual, clique em Sim .

  3. Em Gerenciador de Soluções, expanda a pasta Temas.

  4. Clique duas vezes em Generic.xaml.

    Generic.xaml é aberto no WPF Designer.

  5. No modo de exibição XAML, substitua todas as ocorrências de "CustomControl1" com "ButtonWithDesignTime".

  6. Abra ButtonWithDesignTime.cs ou ButtonWithDesignTime.vb no Editor de Códigos.

  7. Substitua o código gerado automaticamente pelo código a seguir.O controle personalizado Button herda de e exibe o texto "modo de design ativo" quando o botão aparece no designer.

    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.Windows.Controls
    Imports System.Windows.Media
    Imports System.ComponentModel
    
    Public Class ButtonWithDesignTime
        Inherits Button
    
        Public Sub New()
            ' The GetIsInDesignMode check and the following design-time 
            ' code are optional and shown only for demonstration.
            If DesignerProperties.GetIsInDesignMode(Me) Then
                Content = "Design mode active"
            End If
    
        End Sub
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Windows.Controls;
    using System.Windows.Media;
    using System.ComponentModel;
    
    namespace CustomControlLibrary
    {
        public class ButtonWithDesignTime : Button
        {
            public ButtonWithDesignTime()
            {
                // The GetIsInDesignMode check and the following design-time 
                // code are optional and shown only for demonstration.
                if (DesignerProperties.GetIsInDesignMode(this))
                {
                    Content = "Design mode active";
                }
            }
        }
    }
    
  8. Defina o caminho de saída do projeto para "bin\".

  9. Crie a solução.

Criando o Conjunto de Módulos (Assembly) de Metadados em Tempo de Design

Código em tempo de design é implantado em conjuntos de módulos (assemblies) de metadados especiais.Para essa explicação passo a passo, a implementação menu de contexto é implantada em um conjunto de módulos (assembly) denominado CustomControlLibrary.VisualStudio.Design.

Para criando o conjunto de módulos (assembly) de metadados em tempo de design

  1. Adicione um novo projeto de biblioteca de classes no Visual Basic ou Visual C# denominado CustomControlLibrary.VisualStudio.Design à solução.

  2. conjunto caminho de saída do projeto para "..\CustomControlLibrary\bin\ ".Isso mantém o conjunto de módulos (assembly) do controle e o conjunto de módulos (assembly) de metadados na mesma pasta, o que permite a descoberta de metadados para os designers.

  3. Adicione referências para os seguintes conjuntos de módulos (assemblies) WPF.

    • PresentationCore

    • PresentationFramework

    • WindowsBase

  4. Adicione referências para os seguintes conjuntos de módulos (assemblies) WPF Designer:

    • Microsoft.Windows.Design

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  5. Adicione uma referência ao projeto CustomControlLibrary.

  6. Em Gerenciador de Soluções, altere o nome do arquivo de código Class1 para Metadata.cs ou Metadata.vb.Se um caixa de mensagem aparecer que pergunta se você deseja executar uma renomeação para todas as referências no projeto atual, clique em Sim .

  7. Substitua o código gerado automaticamente pelo código a seguir.Esse código cria um AttributeTable que anexa a implementação personalizada em tempo de design à classe ButtonWithDesignTime.

    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports System.ComponentModel
    Imports System.Windows.Media
    Imports System.Windows.Controls
    Imports System.Windows
    Imports CustomControlLibrary
    Imports Microsoft.Windows.Design.Features
    Imports Microsoft.Windows.Design.Metadata
    Imports CustomControlLibrary.VisualStudio.Design.SliderAdornerLib
    
    ' Container for any general design-time metadata to initialize.
    ' Designers look for a type in the design-time assembly that 
    ' implements IRegisterMetadata. If found, designers instantiate 
    ' this class and call its Register() method automatically.
    Friend Class Metadata
        Implements IRegisterMetadata
    
        ' Called by the designer to register any design-time metadata.
        Public Sub Register() Implements IRegisterMetadata.Register
            Dim builder As New AttributeTableBuilder()
    
            ' Add the menu provider to the design-time metadata.
            builder.AddCustomAttributes(GetType(ButtonWithDesignTime), _
                                        New FeatureAttribute(GetType(CustomContextMenuProvider)))
    
            MetadataStore.AddAttributeTable(builder.CreateTable())
        End Sub
    
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    using System.Windows.Media;
    using System.Windows.Controls;
    using System.Windows;
    
    using CustomControlLibrary;
    using Microsoft.Windows.Design.Features;
    using Microsoft.Windows.Design.Metadata;
    using SliderAdornerLib;
    
    namespace CiderPropertiesTester
    {
        // Container for any general design-time metadata to initialize.
        // Designers look for a type in the design-time assembly that 
        // implements IRegisterMetadata. If found, designers instantiate 
        // this class and call its Register() method automatically.
        internal class Metadata : IRegisterMetadata
        {
            // Called by the designer to register any design-time metadata.
            public void Register()
            {
                AttributeTableBuilder builder = new AttributeTableBuilder();
    
                // Add the menu provider to the design-time metadata.
                builder.AddCustomAttributes(
                    typeof(ButtonWithDesignTime), 
                    new FeatureAttribute(typeof(CustomContextMenuProvider)));
    
                MetadataStore.AddAttributeTable(builder.CreateTable());
            }
        }
    }
    
  8. Salve a solução.

Implemente o provedor menu.

O provedor de adorno é implementado em um tipo denominado CustomContextMenuProvider.Este adorner MenuAction permite definir o controle da Background propriedade em tempo de design.

Implemente o provedor menu.

  1. Adicione uma nova classe denominada CustomContextMenuProvider ao projeto CustomControlLibrary.Design.

  2. No Editor de Códigos de CustomContextMenuProvider, substitua o código gerado automaticamente pelo código a seguir.Esse código implementa um PrimarySelectionContextMenuProvider que fornece uma adorner personalizado MenuAction.

    Imports System
    Imports System.Collections.Generic
    Imports System.Text
    Imports Microsoft.Windows.Design.Interaction
    Imports System.Windows
    Imports Microsoft.Windows.Design.Model
    Imports System.Windows.Controls
    Imports System.Windows.Media
    
    ' The CustomContextMenuProvider class provides two context menu items
    ' at design time. These are implemented with the MenuAction class.
    Class CustomContextMenuProvider
        Inherits PrimarySelectionContextMenuProvider
    
        Private setBackgroundToBlueMenuAction As MenuAction
        Private clearBackgroundMenuAction As MenuAction
    
        ' The provider's constructor sets up the MenuAction objects 
        ' and the the MenuGroup which holds them.
        Public Sub New()
    
            ' Set up the MenuAction which sets the control's 
            ' background to Blue.
            setBackgroundToBlueMenuAction = New MenuAction("Blue")
            setBackgroundToBlueMenuAction.Checkable = True
            AddHandler setBackgroundToBlueMenuAction.Execute, AddressOf SetBackgroundToBlue_Execute
    
            ' Set up the MenuAction which sets the control's 
            ' background to its default value.
            clearBackgroundMenuAction = New MenuAction("Cleared")
            clearBackgroundMenuAction.Checkable = True
            AddHandler clearBackgroundMenuAction.Execute, AddressOf ClearBackground_Execute
    
            ' Set up the MenuGroup which holds the MenuAction items.
            Dim backgroundFlyoutGroup As New MenuGroup("SetBackgroundsGroup", "Set Background")
    
            ' If HasDropDown is false, the group appears inline, 
            ' instead of as a flyout. Set to true.
            backgroundFlyoutGroup.HasDropDown = True
            backgroundFlyoutGroup.Items.Add(setBackgroundToBlueMenuAction)
            backgroundFlyoutGroup.Items.Add(clearBackgroundMenuAction)
            Me.Items.Add(backgroundFlyoutGroup)
    
            ' The UpdateItemStatus event is raised immediately before 
            ' this provider shows its tabs, which provides the opportunity 
            ' to set states.
            AddHandler UpdateItemStatus, AddressOf CustomContextMenuProvider_UpdateItemStatus
    
        End Sub
    
        ' The following method handles the UpdateItemStatus event.
        ' It sets the MenuAction states according to the state
        ' of the control's Background property. This method is
        ' called before the context menu is shown.
        Sub CustomContextMenuProvider_UpdateItemStatus( _
            ByVal sender As Object, _
            ByVal e As MenuActionEventArgs)
    
            ' Turn everything on, and then based on the value 
            ' of the BackgroundProperty, selectively turn some off.
            clearBackgroundMenuAction.Checked = False
            clearBackgroundMenuAction.Enabled = True
            setBackgroundToBlueMenuAction.Checked = False
            setBackgroundToBlueMenuAction.Enabled = True
    
            ' Get a ModelItem which represents the selected control. 
            Dim selectedControl As ModelItem = _
                e.Selection.PrimarySelection
    
            ' Get the value of the Background property from the ModelItem.
            Dim backgroundProperty As ModelProperty = _
                selectedControl.Properties(Control.BackgroundProperty)
    
            ' Set the MenuAction items appropriately.
            If Not backgroundProperty.IsSet Then
                clearBackgroundMenuAction.Checked = True
                clearBackgroundMenuAction.Enabled = False
            ElseIf backgroundProperty.ComputedValue.Equals(Brushes.Blue) Then
                setBackgroundToBlueMenuAction.Checked = True
                setBackgroundToBlueMenuAction.Enabled = False
            End If
    
        End Sub
    
        ' The following method handles the Execute event. 
        ' It sets the Background property to its default value.
        Sub ClearBackground_Execute( _
            ByVal sender As Object, _
            ByVal e As MenuActionEventArgs)
    
            Dim selectedControl As ModelItem = e.Selection.PrimarySelection
            selectedControl.Properties(Control.BackgroundProperty).ClearValue()
    
        End Sub
    
        ' The following method handles the Execute event. 
        ' It sets the Background property to Brushes.Blue.
        Sub SetBackgroundToBlue_Execute( _
            ByVal sender As Object, _
            ByVal e As MenuActionEventArgs)
    
            Dim selectedControl As ModelItem = e.Selection.PrimarySelection
            selectedControl.Properties(Control.BackgroundProperty).SetValue(Brushes.Blue)
    
        End Sub
    
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Windows.Design.Interaction;
    using System.Windows;
    using Microsoft.Windows.Design.Model;
    using System.Windows.Controls;
    using System.Windows.Media;
    
    namespace SliderAdornerLib
    {
        // The CustomContextMenuProvider class provides two context menu items
        // at design time. These are implemented with the MenuAction class.
        class CustomContextMenuProvider : PrimarySelectionContextMenuProvider
        {
            private MenuAction setBackgroundToBlueMenuAction;
            private MenuAction clearBackgroundMenuAction;
    
            // The provider's constructor sets up the MenuAction objects 
            // and the the MenuGroup which holds them.
            public CustomContextMenuProvider()
            {   
                // Set up the MenuAction which sets the control's 
                // background to Blue.
                setBackgroundToBlueMenuAction = new MenuAction("Blue");
                setBackgroundToBlueMenuAction.Checkable = true;
                setBackgroundToBlueMenuAction.Execute += 
                    new EventHandler<MenuActionEventArgs>(SetBackgroundToBlue_Execute);
    
                // Set up the MenuAction which sets the control's 
                // background to its default value.
                clearBackgroundMenuAction = new MenuAction("Cleared");
                clearBackgroundMenuAction.Checkable = true;
                clearBackgroundMenuAction.Execute += 
                    new EventHandler<MenuActionEventArgs>(ClearBackground_Execute);
    
                // Set up the MenuGroup which holds the MenuAction items.
                MenuGroup backgroundFlyoutGroup = 
                    new MenuGroup("SetBackgroundsGroup", "Set Background");
    
                // If HasDropDown is false, the group appears inline, 
                // instead of as a flyout. Set to true.
                backgroundFlyoutGroup.HasDropDown = true;
                backgroundFlyoutGroup.Items.Add(setBackgroundToBlueMenuAction);
                backgroundFlyoutGroup.Items.Add(clearBackgroundMenuAction);
                this.Items.Add(backgroundFlyoutGroup);
    
                // The UpdateItemStatus event is raised immediately before 
                // this provider shows its tabs, which provides the opportunity 
                // to set states.
                UpdateItemStatus += 
                    new EventHandler<MenuActionEventArgs>(
                        CustomContextMenuProvider_UpdateItemStatus);
            }
    
            // The following method handles the UpdateItemStatus event.
            // It sets the MenuAction states according to the state
            // of the control's Background property. This method is
            // called before the context menu is shown.
            void CustomContextMenuProvider_UpdateItemStatus(
                object sender, 
                MenuActionEventArgs e)
            {
                // Turn everything on, and then based on the value 
                // of the BackgroundProperty, selectively turn some off.
                clearBackgroundMenuAction.Checked = false;
                clearBackgroundMenuAction.Enabled = true;
                setBackgroundToBlueMenuAction.Checked = false;
                setBackgroundToBlueMenuAction.Enabled = true;
    
                // Get a ModelItem which represents the selected control. 
                ModelItem selectedControl = e.Selection.PrimarySelection;
    
                // Get the value of the Background property from the ModelItem.
                ModelProperty backgroundProperty = 
                    selectedControl.Properties[Control.BackgroundProperty];
    
                // Set the MenuAction items appropriately.
                if (!backgroundProperty.IsSet)
                {
                    clearBackgroundMenuAction.Checked = true;
                    clearBackgroundMenuAction.Enabled = false;
                }
                else if (backgroundProperty.ComputedValue == Brushes.Blue)
                {
                    setBackgroundToBlueMenuAction.Checked = true;
                    setBackgroundToBlueMenuAction.Enabled = false;
                }
            }
    
            // The following method handles the Execute event. 
            // It sets the Background property to its default value.
            void ClearBackground_Execute(
                object sender, 
                MenuActionEventArgs e)
            {
                ModelItem selectedControl = e.Selection.PrimarySelection;
                selectedControl.Properties[Control.BackgroundProperty].ClearValue();
            }
    
            // The following method handles the Execute event. 
            // It sets the Background property to Brushes.Blue.
            void SetBackgroundToBlue_Execute(
                object sender, 
                MenuActionEventArgs e)
            {
                ModelItem selectedControl = e.Selection.PrimarySelection;
                selectedControl.Properties[Control.BackgroundProperty].SetValue(Brushes.Blue);
            }
        }
    }
    
  3. Crie a solução.

Testando a Implementação em Tempo de Design

Você pode usar o controle ButtonWithDesignTime do modo como você usaria qualquer outro controle WPF.O WPF Designer trata a criação de todos os objetos em tempo de design.

Para testar a implementação em tempo de design

  1. Adicione um novo projeto de aplicativo WPF no Visual C# denominado DemoApplication à solução.

    Window1.xaml é aberto no WPF Designer.

  2. Adicione uma referência ao projeto CustomControlLibrary.

  3. No modo de exibição XAML, substitua o XAML gerado automaticamente pelo seguinte XAML.Este XAML adiciona uma referência ao namespace CustomControlLibrary e adiciona o controle personalizado ButtonWithDesignTime.O botão aparece no modo Design com um plano de fundo vermelho, indicando que o controle está no modo de design.Se o botão não for exibido, talvez você precise clicar na Barra de Informações na parte superior do designer para recarregar o modo de exibição.

    <Window x:Class="DemoApplication.Window1"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cc="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <cc:ButtonWithDesignTime Margin="30,30,30,30" Background="#FFD4D0C8"></cc:ButtonWithDesignTime>
        </Grid>
    </Window>
    
    <Window x:Class="DemoApplication.Window1"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cc="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"
        Title="Window1" Height="300" Width="300">
        <Grid>
            <cc:ButtonWithDesignTime Margin="30,30,30,30" Background="#FFD4D0C8"></cc:ButtonWithDesignTime>
        </Grid>
    </Window>
    
  4. No modo Design, clique no controle ButtonWithDesignTime para selecioná-lo.

  5. Clique com o botão direito do mouse no controle ButtonWithDesignTime, aponte para Conjunto de plano de fundo e selecione Blue .

    Plano de fundo do controle é definido como azul.No modo XAML, a propriedade Background é definida para o valor especificado pelo controle .

  6. Execute o projeto DemoApplication.

    Em tempo de execução, o botão possui o plano de fundo que é definido com o menu de atalho.

Próximas etapas

Você pode adicionar mais recursos em tempo de design personalizados para os controles personalizados.

Consulte também

Tarefas

Como: Criar um MenuAction

Referência

PrimarySelectionContextMenuProvider

Outros recursos

Conceitos de Extensibilidade Avançada

Extensibilidade do WPF Designer