更新 : 2007 年 11 月
このチュートリアルでは、WPF (Windows Presentation Foundation) カスタム コントロール用のデザイン時メニュー プロバイダを作成する方法について説明します。このショートカット メニュー項目を使用して、カスタム ボタン コントロールの Background プロパティ値を設定できます。完全なコードの一覧については、「方法 : MenuAction を作成する」を参照してください。
このチュートリアルでは次のタスクを行います。
WPF カスタム コントロール ライブラリ プロジェクトを作成する。
デザイン時メタデータに対する個別のアセンブリを作成する。
メニュー プロバイダを実装する。
デザイン時にコントロールを使用する。
このチュートリアルを終了すると、カスタム コントロール用メニュー プロバイダを作成する方法を習得できます。
![]() |
---|
使用している設定またはエディションによっては、ヘルプの記載と異なるダイアログ ボックスやメニュー コマンドが表示される場合があります。設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。詳細については、「Visual Studio の設定」を参照してください。 |
前提条件
このチュートリアルを完了するには、次のコンポーネントが必要です。
- Visual Studio 2008.
カスタム コントロールの作成
最初に、カスタム コントロールのプロジェクトを作成します。コントロールは、デザイン時コードが少量のシンプルなボタンにします。このボタンは、GetIsInDesignMode メソッドを使用して、デザイン時動作を実装します。
カスタム コントロールを作成するには
Visual Basic または Visual C# で CustomControlLibrary という名前の新しい WPF カスタム コントロール ライブラリ プロジェクトを作成します。
コード エディタで CustomControl1 のコードが開きます。
ソリューション エクスプローラで、コード ファイル名を ButtonWithDesignTime.cs または ButtonWithDesignTime.vb に変更します。このプロジェクト内のすべての参照に対する名前を変更するかどうかを確認するメッセージが表示されたら、[はい] をクリックします。
ソリューション エクスプローラで、Themes フォルダを展開します。
Generic.xaml をダブルクリックします。
Generic.xaml が WPF デザイナで開きます。
XAML ビューで、すべての "CustomControl1" を "ButtonWithDesignTime" に置き換えます。
コード エディタで ButtonWithDesignTime.cs または ButtonWithDesignTime.vb を開きます。
自動的に生成されたコードを次のコードで置き換えます。このコードは、Button からの継承で、ボタンがデザイナに表示されると、"Design mode active" というテキストが表示されます。
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"; } } } }
プロジェクトの出力パスを "bin\" に設定します。
ソリューションをビルドします。
デザイン時メタデータ アセンブリの作成
デザイン時コードは、特殊なメタデータ アセンブリで配布されます。このチュートリアルでは、コンテキスト メニューの実装は、CustomControlLibrary.VisualStudio.Design という名前のアセンブリで配布されます。
デザイン時メタデータ アセンブリを作成するには
Visual Basic または Visual C# の CustomControlLibrary.VisualStudio.Design という名前の新しいクラス ライブラリ プロジェクトをソリューションに追加します。
プロジェクトの出力パスを "..\CustomControlLibrary\bin\" に設定します。これにより、コントロールのアセンブリとメタデータのアセンブリを同じフォルダ内に置き、デザイナによりメタデータが検出されるようにします。
次の WPF アセンブリへの参照を追加します。
PresentationCore
PresentationFramework
WindowsBase
次の WPF デザイナアセンブリへの参照を追加します。
Microsoft.Windows.Design
Microsoft.Windows.Design.Extensibility
Microsoft.Windows.Design.Interaction
CustomControlLibrary プロジェクトへの参照を追加します。
ソリューション エクスプローラで、Class1 コード ファイル名を Metadata.cs または Metadata.vb に変更します。このプロジェクト内のすべての参照について名前を変更するかどうかを確認するメッセージが表示されたら、[はい] をクリックします。
自動的に生成されたコードを次のコードに置き換えます。このコードにより、カスタム デザイン時実装を ButtonWithDesignTime クラスに関連付ける AttributeTable が作成されます。
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()); } } }
ソリューションを保存します。
メニュー プロバイダの実装
メニュー プロバイダは CustomContextMenuProvider という名前の型で実装されます。提供される MenuAction により、コントロールの Background プロパティをデザイン時に設定できるようになります。
メニュー プロバイダを実装するには
CustomContextMenuProvider という名前の新しいクラスを CustomControlLibrary.VisualStudio.Design プロジェクトに追加します。
CustomContextMenuProvider のコード エディタで、自動的に生成されたコードを次のコードに置き換えます。このコードにより、カスタム MenuAction を提供する PrimarySelectionContextMenuProvider を実装します。
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); } } }
ソリューションをビルドします。
デザイン時実装のテスト
ButtonWithDesignTime コントロールは、他の WPF コントロールと同じように使用できます。WPF デザイナは、すべてのデザイン時オブジェクトの作成を処理します。
デザイン時実装をテストするには
Visual Basic または Visual C# の DemoApplication という名前の WPF アプリケーション プロジェクトをソリューションに追加します。
WPF デザイナで Window1.xaml が開きます。
CustomControlLibrary プロジェクトへの参照を追加します。
XAML ビューで、自動的に生成された XAML を次の XAML に置き換えます。この XAML により、CustomControlLibrary 名前空間への参照が追加され、ButtonWithDesignTime カスタム コントロールが追加されます。ボタンは、"Design mode active" というテキストと共にデザイン ビューに表示されます。これは、現在デザイン モードであることを示すものです。ボタンが表示されない場合は、デザイナの一番上の情報バーをクリックして、ビューの再読み込みを行う必要があります。
<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>
デザイン ビューで、ButtonWithDesignTime コントロールをクリックして選択します。
ButtonWithDesignTime コントロールを右クリックし、[Set Background] をポイントして、[Blue] をクリックします。
コントロールの背景が青に設定されます。XAML ビューで、Background プロパティは、メニュー アクションによって指定された値に設定されます。
DemoApplication プロジェクトを実行します。
実行時、ボタンは、ショートカット メニューで設定した背景になります。
次の手順
カスタム コントロールに、さらにカスタム デザイン時機能を追加できます。
コントロールのデザイン時にカスタム装飾を追加します。詳細については、「チュートリアル : デザイン時装飾の作成」を参照してください。
[プロパティ] ウィンドウで使用できるカスタム型用のエディタを作成します。詳細については、「方法 : 値エディタを作成する」を参照してください。
参照
処理手順
参照
PrimarySelectionContextMenuProvider