次の方法で共有


チュートリアル: メニュー プロバイダーの作成

[このドキュメントはプレビューのみを目的としており、以降のリリースで変更される可能性があります。プレースホルダーとして空白のトピックが含まれています。]

このチュートリアルでは、WPF (Windows Presentation Foundation) カスタム コントロール用のデザイン時メニュー プロバイダーを作成する方法について説明します。 このショートカット メニュー項目を使用して、カスタム ボタン コントロールの Background プロパティ値を設定できます。 完全なコード一覧については、WPF Designer Extensibility Samples (WPF デザイナー機能拡張のサンプル) サイトに掲載されている「Context Menu Provider (コンテキスト メニュー プロバイダー)」のサンプルを参照してください。

このチュートリアルでは次のタスクを行います。

  • WPF カスタム コントロール ライブラリ プロジェクトを作成する。

  • デザイン時メタデータに対する個別のアセンブリを作成する。

  • メニュー プロバイダーを実装する。

  • デザイン時にコントロールを使用する。

このチュートリアルを終了すると、カスタム コントロール用メニュー プロバイダーを作成する方法を習得できます。

注意

実際に画面に表示されるダイアログ ボックスとメニュー コマンドは、アクティブな設定またはエディションによっては、ヘルプの説明と異なる場合があります。設定を変更するには、[ツール] メニューの [設定のインポートとエクスポート] をクリックします。詳細については、「Visual Studio の設定」を参照してください。

必須コンポーネント

このチュートリアルを実行するには、次のコンポーネントが必要です。

  • Visual Studio 2012 RC.

カスタム コントロールの作成

最初に、カスタム コントロールのプロジェクトを作成します。 コントロールは、デザイン時コードが少量のシンプルなボタンにします。このボタンは、GetIsInDesignMode メソッドを使用して、デザイン時動作を実装します。

カスタム コントロールを作成するには

  1. Visual Basic または Visual C# で CustomControlLibrary という名前の新しい WPF カスタム コントロール ライブラリ プロジェクトを作成します。

    コード エディターで CustomControl1 のコードが開きます。

  2. ソリューション エクスプローラーで、コード ファイル名を ButtonWithDesignTime.cs または ButtonWithDesignTime.vb に変更します。 このプロジェクト内のすべての参照について名前を変更するかどうかをたずねるメッセージ ボックスが開いたら、[はい] をクリックします。

  3. コード エディターで ButtonWithDesignTime.cs または ButtonWithDesignTime.vb を開きます。

  4. 自動的に生成されたコードを次のコードで置き換えます。 このコードは、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";
                }
            }
        }
    }
    
  5. プロジェクトの出力パスを "bin\" に設定します。

  6. ソリューションをビルドします。

デザイン時メタデータ アセンブリの作成

デザイン時コードは、特殊なメタデータ アセンブリで配布されます。 このチュートリアルでは、コンテキスト メニューの実装は、CustomControlLibrary.VisualStudio.Design という名前のアセンブリで配布されます。 詳細については、「デザイン時メタデータの提供」を参照してください。

デザイン時メタデータ アセンブリを作成するには

  1. Visual Basic または Visual C# の CustomControlLibrary.VisualStudio.Design という名前の新しいクラス ライブラリ プロジェクトをソリューションに追加します。

  2. プロジェクトの出力パスを ".. \CustomControlLibrary\bin\" に設定します。 これにより、コントロールのアセンブリとメタデータのアセンブリが同じフォルダー内に配置されるため、デザイナーがメタデータを検出できます。

  3. 次の WPF アセンブリへの参照を追加します。

    • PresentationCore

    • PresentationFramework

    • System.Xaml

    • WindowsBase

  4. 次の WPF Designer アセンブリへの参照を追加します。

    • Microsoft.Windows.Design.Extensibility

    • Microsoft.Windows.Design.Interaction

  5. CustomControlLibrary プロジェクトへの参照を追加します。

  6. ソリューション エクスプローラーで、Class1 コード ファイル名を Metadata.cs または Metadata.vb に変更します。 このプロジェクト内のすべての参照について名前を変更するかどうかをたずねるメッセージ ボックスが開いたら、[はい] をクリックします。

  7. 自動的に生成されたコードを次のコードで置き換えます。 このコードにより、カスタム デザイン時実装を 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.Slid
    
    ' The ProvideMetadata assembly-level attribute indicates to designers
    ' that this assembly contains a class that provides an attribute table. 
    <Assembly: ProvideMetadata(GetType(CustomControlLibrary.VisualStudio.Design.Metadata))> 
    
    ' Container for any general design-time metadata to initialize.
    ' Designers look for a type in the design-time assembly that 
    ' implements IProvideAttributeTable. If found, designers instantiate
    ' this class and access its AttributeTable property automatically.
    Friend Class Metadata
        Implements IProvideAttributeTable
    
        ' Accessed by the designer to register any design-time metadata.
        Public ReadOnly Property AttributeTable() As AttributeTable _
            Implements IProvideAttributeTable.AttributeTable
            Get
                Dim builder As New AttributeTableBuilder()
    
                ' Add the menu provider to the design-time metadata.
                builder.AddCustomAttributes(GetType(ButtonWithDesignTime), _
                                            New FeatureAttribute(GetType(CustomContextMenuProvider)))
    
                Return builder.CreateTable()
            End Get
        End Property
    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 CustomControlLibrary.VisualStudio.Design;
    
    // The ProvideMetadata assembly-level attribute indicates to designers
    // that this assembly contains a class that provides an attribute table. 
    [assembly: ProvideMetadata(typeof(CustomControlLibrary.VisualStudio.Design.Metadata))]
    namespace CustomControlLibrary.VisualStudio.Design
    {
        // Container for any general design-time metadata to initialize.
        // Designers look for a type in the design-time assembly that 
        // implements IProvideAttributeTable. If found, designers instantiate 
        // this class and access its AttributeTable property automatically.
        internal class Metadata : IProvideAttributeTable
        {
            // Accessed by the designer to register any design-time metadata.
            public AttributeTable AttributeTable
            {
                get
                {
                    AttributeTableBuilder builder = new AttributeTableBuilder();
    
                    // Add the menu provider to the design-time metadata.
                    builder.AddCustomAttributes(
                        typeof(ButtonWithDesignTime),
                        new FeatureAttribute(typeof(CustomContextMenuProvider)));
    
                    return builder.CreateTable(); 
                }
            }
        }
    }
    
  8. ソリューションを保存します。

メニュー プロバイダーの実装

メニュー プロバイダーは CustomContextMenuProvider という名前の型で実装されます。 提供される MenuAction により、コントロールの Background プロパティをデザイン時に設定できるようになります。

メニュー プロバイダーを実装するには

  1. CustomContextMenuProvider という名前の新しいクラスを CustomControlLibrary.VisualStudio.Design プロジェクトに追加します。

  2. 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("Background")
    
            ' 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("Background").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("Background").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 CustomControlLibrary.VisualStudio.Design
    {
        // 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["Background"];
    
                // 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["Background"].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["Background"].SetValue(Brushes.Blue);
            }
        }
    }
    
  3. ソリューションをビルドします。

デザイン時実装のテスト

ButtonWithDesignTime コントロールは、他の WPF コントロールと同じように使用できます。 WPF Designerは、すべてのデザイン時オブジェクトの作成を処理します。

デザイン時実装をテストするには

  1. Visual Basic または Visual C# の DemoApplication という名前の WPF アプリケーション プロジェクトをソリューションに追加します。

    WPF Designerで MainWindow.xaml が開きます。

  2. CustomControlLibrary プロジェクトへの参照を追加します。

  3. XAML ビューで、自動的に生成された XAML を次の XAML に置き換えます。 この XAML により、CustomControlLibrary 名前空間への参照が追加され、ButtonWithDesignTime カスタム コントロールが追加されます。 ボタンは、"Design mode active" というテキストと共にデザイン ビューに表示されます。これは、現在デザイン モードであることを示すものです。 ボタンが表示されない場合は、デザイナーの一番上の情報バーをクリックして、ビューの再読み込みを行う必要があります。

    <Window x:Class="DemoApplication.MainWindow"
        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. デザイン ビューで、ButtonWithDesignTime コントロールをクリックして選択します。

  5. ButtonWithDesignTime コントロールを右クリックし、[Set Background] をポイントして、[Blue] をクリックします。

    コントロールの背景が青に設定されます。 XAML ビューで、Background プロパティは、メニュー アクションによって指定された値に設定されます。

  6. DemoApplication プロジェクトを実行します。

    実行時、ボタンは、ショートカット メニューで設定した背景になります。

次の手順

カスタム コントロールに、さらにカスタム デザイン時機能を追加できます。

参照

Reference

PrimarySelectionContextMenuProvider

その他の技術情報

高度な機能拡張という概念

WPF デザイナーの機能拡張

WPF デザイナーの拡張機能のサンプル