Exemplarische Vorgehensweise: Erstellen einer MenuAction
Aktualisiert: November 2007
In dieser exemplarischen Vorgehensweise wird veranschaulicht, wie Sie einen Entwurfszeitmenüanbieter für ein benutzerdefiniertes WPF-Steuerelement (Windows Presentation Foundation) erstellen. Mit diesem Kontextmenüelement können Sie für ein benutzerdefiniertes Schaltflächen-Steuerelement den Wert der Background-Eigenschaft festlegen. Die vollständige Codeauflistung finden Sie unter Gewusst wie: Erstellen einer MenuAction.
Im Verlauf dieser exemplarischen Vorgehensweise führen Sie folgende Aufgaben aus:
Erstellen Sie ein benutzerdefiniertes WPF-Steuerelementbibliothek-Projekt.
Erstellen Sie eine separate Assembly für Entwurfszeitmetadaten.
Implementieren Sie den Menüanbieter.
Verwenden Sie das Steuerelement zur Entwurfszeit.
Nach Abschluss wissen Sie, wie ein Menüanbieter für ein benutzerdefiniertes Steuerelement erstellt wird.
Hinweis: |
---|
Je nach aktivierten Einstellungen oder der verwendeten Edition können sich die angezeigten Dialogfelder und Menübefehle von den in der Hilfe beschriebenen unterscheiden. Klicken Sie zum Ändern der Einstellungen im Menü Extras auf Einstellungen importieren und exportieren. Weitere Informationen finden Sie unter Visual Studio-Einstellungen. |
Vorbereitungsmaßnahmen
Zum Durchführen dieser exemplarischen Vorgehensweise benötigen Sie die folgenden Komponenten:
- Visual Studio 2008.
Erstellen des benutzerdefinierten Steuerelements
Zuerst wird das Projekt für das benutzerdefinierte Steuerelement erstellt. Bei dem Steuerelement handelt es sich um eine einfache Schaltfläche mit wenig Entwurfszeitcode, für die eine GetIsInDesignMode-Methode zum Implementieren eines Entwurfszeitverhaltens verwendet wird.
So erstellen Sie das benutzerdefinierte Steuerelement
Erstellen Sie ein neues benutzerdefiniertes WPF-Steuerelementbibliothek-Projekt in Visual Basic oder Visual C# mit dem Namen CustomControlLibrary.
Der Code für CustomControl1 wird im Code-Editor geöffnet.
Ändern Sie im Projektmappen-Explorer den Namen der Codedatei in ButtonWithDesignTime.cs oder ButtonWithDesignTime.vb. Wenn eine Meldung mit der Frage angezeigt wird, ob Sie eine Umbenennung für alle Verweise in diesem Projekt vornehmen möchten, klicken Sie auf Ja.
Erweitern Sie im Projektmappen-Explorer den Ordner Themes.
Doppelklicken Sie auf Generic.xaml.
Generic.xaml wird im WPF-Designer geöffnet.
Ersetzen Sie in der XAML-Ansicht alle Vorkommen von "CustomControl1" durch "ButtonWithDesignTime".
Öffnen Sie ButtonWithDesignTime.cs bzw. ButtonWithDesignTime.vb im Code-Editor.
Ersetzen Sie den automatisch generierten Code durch den folgenden Code. Dieser Code erbt von Button und zeigt den Text "Design mode active" an, wenn die Schaltfläche im Designer angezeigt wird.
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"; } } } }
Legen Sie den Ausgabepfad des Projekts auf "bin\" fest.
Erstellen Sie die Projektmappe.
Erstellen der Entwurfszeit-Metadatenassembly
Entwurfszeitcode wird in speziellen Metadatenassemblys bereitgestellt. Bei dieser exemplarischen Vorgehensweise wird die Implementierung des Kontextmenüs in einer Assembly mit dem Namen CustomControlLibrary.VisualStudio.Design bereitgestellt.
So erstellen Sie die Entwurfszeit-Metadatenassembly
Fügen Sie der Projektmappe ein neues Klassenbibliothek-Projekt in Visual Basic oder Visual C# mit dem Namen CustomControlLibrary.VisualStudio.Design hinzu.
Legen Sie den Ausgabepfad des Projekts auf "..\CustomControlLibrary\bin\" fest. Dadurch wird die Assembly des Steuerelements im selben Ordner wie die Metadatenassembly gespeichert, wodurch Designern die Metadatensuche ermöglicht wird.
Fügen Sie Verweise auf die folgenden WPF-Assemblys hinzu.
PresentationCore
PresentationFramework
WindowsBase
Fügen Sie Verweise auf die folgenden WPF-Designer-Assemblys hinzu.
Microsoft.Windows.Design
Microsoft.Windows.Design.Extensibility
Microsoft.Windows.Design.Interaction
Fügen Sie einen Verweis auf das CustomControlLibrary-Projekt hinzu.
Ändern Sie im Projektmappen-Explorer den Namen der Class1-Codedatei in Metadata.cs oder Metadata.vb. Wenn eine Meldung mit der Frage angezeigt wird, ob Sie eine Umbenennung für alle Verweise in diesem Projekt vornehmen möchten, klicken Sie auf Ja.
Ersetzen Sie den automatisch generierten Code durch den folgenden Code. Durch diesen Code wird eine AttributeTable erstellt, mit der die benutzerdefinierte Entwurfszeitimplementierung an die ButtonWithDesignTime-Klasse anfügt wird.
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()); } } }
Speichern Sie die Projektmappe.
Implementieren des Menüanbieters
Der Menüanbieter wird in einem Typ mit dem Namen CustomContextMenuProvider implementiert. Durch die bereitgestellte MenuAction kann die Background-Eigenschaft des Steuerelements zur Entwurfszeit festgelegt werden.
So implementieren Sie den Menüanbieter
Fügen Sie dem CustomControlLibrary.VisualStudio.Design-Projekt eine neue Klasse mit dem Namen CustomContextMenuProvider hinzu.
Ersetzen Sie im Code-Editor für CustomContextMenuProvider den automatisch generierten Code durch den folgenden Code. Mit diesem Code wird ein PrimarySelectionContextMenuProvider implementiert, der eine benutzerdefinierte MenuAction bereitstellt.
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); } } }
Erstellen Sie die Projektmappe.
Testen der Entwurfszeitimplementierung
Sie können das ButtonWithDesignTime-Steuerelement auf dieselbe Art wie jedes andere WPF-Steuerelement verwenden. Der WPF-Designer verwaltet die Erstellung aller Entwurfszeitobjekte.
So testen Sie die Entwurfszeitimplementierung
Fügen Sie der Projektmappe ein neues WPF-Anwendungsprojekt in Visual Basic oder Visual C# mit dem Namen DemoApplication hinzu.
In WPF-Designer wird die Datei Window1.xaml geöffnet.
Fügen Sie einen Verweis auf das CustomControlLibrary-Projekt hinzu.
Ersetzen Sie in der XAML-Ansicht das automatisch generierte XAML durch das folgende XAML. Mit diesem XAML werden ein Verweis auf den CustomControlLibrary-Namespace sowie das benutzerdefinierte ButtonWithDesignTime-Steuerelement hinzugefügt. Die Schaltfläche wird in der Entwurfsansicht mit dem Text "Design mode active" angezeigt, was darauf hindeutet, dass sie sich im Entwurfsmodus befindet. Wenn die Schaltfläche nicht angezeigt wird, müssen Sie möglicherweise auf die Informationsleiste am oberen Rand des Designers klicken, um die Ansicht zu aktualisieren.
<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>
Klicken Sie in der Entwurfsansicht auf das ButtonWithDesignTime-Steuerelement, um es auszuwählen.
Klicken Sie mit der rechten Maustaste auf das ButtonWithDesignTime-Steuerelement, zeigen Sie auf Hintergrund festlegen, und wählen Sie Blau aus.
Der Hintergrund des Steuerelements wird auf blau festgelegt. In der XAML-Ansicht wird die Background-Eigenschaft auf den von der Menüaktion angegebenen Wert festgelegt.
Führen Sie das DemoApplication-Projekt aus.
Zur Laufzeit hat die Schaltfläche den Hintergrund, den Sie mit dem Kontextmenü festlegen.
Nächste Schritte
Sie können benutzerdefinierten Steuerelementen weitere benutzerdefinierte Entwurfszeitfeatures hinzufügen.
Fügen Sie der Entwurfszeit des Steuerelements einen benutzerdefinierten Adorner hinzu. Weitere Informationen finden Sie unter Exemplarische Vorgehensweise: Erstellen eines Entwurfszeitadorners.
Erstellen Sie einen Editor für einen benutzerdefinierten Typ, den Sie im Eigenschaftenfenster verwenden können. Weitere Informationen finden Sie unter Gewusst wie: Erstellen eines Wert-Editors.
Siehe auch
Aufgaben
Gewusst wie: Erstellen einer MenuAction
Referenz
PrimarySelectionContextMenuProvider