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
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.
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 .
Em Gerenciador de Soluções, expanda a pasta Temas.
Clique duas vezes em Generic.xaml.
Generic.xaml é aberto no WPF Designer.
No modo de exibição XAML, substitua todas as ocorrências de "CustomControl1" com "ButtonWithDesignTime".
Abra ButtonWithDesignTime.cs ou ButtonWithDesignTime.vb no Editor de Códigos.
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"; } } } }
Defina o caminho de saída do projeto para "bin\".
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
Adicione um novo projeto de biblioteca de classes no Visual Basic ou Visual C# denominado CustomControlLibrary.VisualStudio.Design à solução.
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.
Adicione referências para os seguintes conjuntos de módulos (assemblies) WPF.
PresentationCore
PresentationFramework
WindowsBase
Adicione referências para os seguintes conjuntos de módulos (assemblies) WPF Designer:
Microsoft.Windows.Design
Microsoft.Windows.Design.Extensibility
Microsoft.Windows.Design.Interaction
Adicione uma referência ao projeto CustomControlLibrary.
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 .
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()); } } }
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.
Adicione uma nova classe denominada CustomContextMenuProvider ao projeto CustomControlLibrary.Design.
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); } } }
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
Adicione um novo projeto de aplicativo WPF no Visual C# denominado DemoApplication à solução.
Window1.xaml é aberto no WPF Designer.
Adicione uma referência ao projeto CustomControlLibrary.
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>
No modo Design, clique no controle ButtonWithDesignTime para selecioná-lo.
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 .
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.
Adicione um adorner personalizado a tempo de design do seu controle.Para obter mais informações, consulte Demonstra Passo a passo: Criar um adorno de time de design.
Criar um editor de cores personalizado, que pode ser usado na Janela de Propriedades.Para obter mais informações, consulte Como: Criar um editor de valores.
Consulte também
Tarefas
Referência
PrimarySelectionContextMenuProvider