チュートリアル : カテゴリ エディターの作成
WPF Designer for Visual Studio の機能拡張モデルを使用すると、カテゴリ エディターという、プロパティのカテゴリ用のカスタム エディターを作成できます。 カテゴリ エディターを使用すると、テキスト関連プロパティなど、1 つのカテゴリに属する互いに関連するプロパティを編集するためのカスタム ユーザー インターフェイスを提供できます。 このチュートリアルでは、コントロールのテキスト関連プロパティを編集するためのカテゴリ エディターを作成します。
このチュートリアルでは次のタスクを行います。
WPF カスタム コントロール プロジェクトを作成する。
そのコントロールのテキスト関連プロパティを編集するために使用されるカテゴリ エディターを作成する。
コントロールのカテゴリ エディターを表す CategoryEditor から継承するクラスを作成する。
新しい拡張エディターを登録するために IProvideAttributeTable インターフェイスを実装するクラスを作成する。
デザイン時にカテゴリ エディターをテストする。
必須コンポーネント
このチュートリアルを実行するには、次のコンポーネントが必要です。
- Visual Studio 2010.
カスタム コントロールの作成
最初に、カスタム コントロールのプロジェクトを作成します。 コントロールは、デザイン時コードが少量のシンプルなボタンにします。このボタンは、GetIsInDesignMode メソッドを使用して、デザイン時動作を実装します。
カスタム コントロールを作成するには
Visual C# で CustomControlLibrary という名前の新しい WPF カスタム コントロール ライブラリ プロジェクトを作成します。
コード エディターで CustomControl1 のコードが開きます。
CustomControl1 のコード エディターで、CustomControlLibrary 名前空間のコードを次のコードに置き換えます。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace CustomControlLibrary { public class CustomControl1 : Button { public CustomControl1() { if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)) { Content = "In design mode"; } } } }
プロジェクトの出力パスを "bin\" に設定します。
ソリューションをビルドします。
プロパティ情報をカプセル化するクラスの作成
作成されるカテゴリ エディターは、フォントおよび関連するプロパティについての情報を必要とするため、それらの情報をカプセル化するクラスをここで作成します。 このクラスは、カテゴリ エディターによってデータ ソースとして使われます。
フォント プロパティ情報をカプセル化するクラスを作成するには
Visual C# で CustomControlLibrary.Design という名前の新しい WPF カスタム コントロール ライブラリ プロジェクトをソリューションに追加します。
コード エディターで CustomControl1 のコードが開きます。
ソリューション エクスプローラーで、CustomControl1 ファイルを CustomControlLibrary.Design プロジェクトから削除します。
ソリューション エクスプローラーで、Themes フォルダーを CustomControlLibrary.Design プロジェクトから削除します。
次の WPF デザイナー アセンブリへの参照を追加します。
Microsoft.Windows.Design.Extensibility
Microsoft.Windows.Design.Interaction
CustomControlLibrary プロジェクトへの参照を追加します。
プロジェクトの出力パスを ".. \CustomControlLibrary\bin\" に設定します。 これにより、コントロールのアセンブリとメタデータのアセンブリが同じフォルダー内に配置されるため、デザイナーがメタデータを検出できます。
FontList という名前の新しいクラスを CustomControlLibrary.Design プロジェクトに追加します。
FontList のコード エディターで、自動生成されたコードを次のコードに置き換えます。
using System; using System.Linq; using System.Collections.Generic; using System.Text; using System.Windows.Media; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Data; using System.Globalization; namespace CustomControlLibrary.Design { public class FontList : ObservableCollection<FontFamily> { public FontList() { foreach (FontFamily ff in Fonts.SystemFontFamilies) { Add(ff); } } } public class FontSizeList : ObservableCollection<double> { public FontSizeList() { Add(8); Add(9); Add(10); Add(11); Add(12); Add(14); Add(16); Add(18); Add(20); } } public class FontStyleConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { FontStyle fs = (FontStyle)value; return fs == FontStyles.Italic; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { bool isSet = (bool)value; if (isSet) { return FontStyles.Italic; } } return FontStyles.Normal; } } public class FontWeightConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { FontWeight fs = (FontWeight)value; return fs == FontWeights.Bold; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { bool isSet = (bool)value; if (isSet) { return FontWeights.Bold; } } return FontWeights.Normal; } } }
カテゴリ エディターのテンプレートの作成
カテゴリ エディターは、XAML データ テンプレートを使用して作成されます。 これは、いくつかのテキスト関連プロパティにバインドされる簡単なユーザー インターフェイスです。
カテゴリ エディターのテンプレートを作成するには
EditorResources という名前の新しいクラスを CustomControlLibrary.Design プロジェクトに追加します。
EditorResources のコード エディターで、自動的に生成されたコードを次のコードに置き換えます。
namespace CustomControlLibrary.Design { using System; using System.Collections.Generic; using System.Text; using System.Windows; public partial class EditorResources : ResourceDictionary { public EditorResources() : base() { InitializeComponent(); } } }
[プロジェクト] メニューの [リソース ディクショナリの追加] をクリックします。
フォームに EditorResources.xaml という名前を付け、[追加] をクリックします。
EditorResources の XAML ビューで、自動的に生成された XAML を次の XAML に置き換えます。
<ResourceDictionary xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:PropertyEditing="clr-namespace:Microsoft.Windows.Design.PropertyEditing;assembly=Microsoft.Windows.Design.Interaction" xmlns:Local="clr-namespace:CustomControlLibrary.Design" xmlns:Media="clr-namespace:System.Windows.Media;assembly=PresentationCore" xmlns:sys="clr-namespace:System;assembly=mscorlib" x:Class="CustomControlLibrary.Design.EditorResources"> <Local:FontList x:Key="FontFamilyList"/> <Local:FontSizeList x:Key="FontSizeList"/> <Local:FontStyleConverter x:Key="FontStyleConverter"/> <Local:FontWeightConverter x:Key="FontWeightConverter"/> <DataTemplate x:Key="TextCategoryEditorTemplate"> <StackPanel Margin="5"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="1*"/> <ColumnDefinition Width="50"/> </Grid.ColumnDefinitions> <ComboBox Grid.Column="0" Margin="2" ItemsSource="{Binding Source={StaticResource FontFamilyList}}" SelectedItem="{Binding [FontFamily].PropertyValue.Value}"/> <ComboBox Grid.Column="1" Margin="2" ItemsSource="{Binding Source={StaticResource FontSizeList}}" SelectedItem="{Binding [FontSize].PropertyValue.Value}"/> </Grid> <StackPanel Orientation="Horizontal"> <CheckBox Margin="2" Content="Bold" IsChecked="{Binding Path=[FontWeight].PropertyValue.Value, Converter={StaticResource FontWeightConverter}}"/> <CheckBox Margin="2" Content="Italic" IsChecked="{Binding Path=[FontStyle].PropertyValue.Value, Converter={StaticResource FontStyleConverter}}"/> </StackPanel> </StackPanel> </DataTemplate> </ResourceDictionary>
ソリューションをビルドします。
テンプレートのカプセル化とカテゴリ エディターの登録
カテゴリ エディター用のテンプレートを作成した後は、このテンプレートをカスタム エディターとして使用するために CategoryEditor 派生クラスを作成し、新しいカテゴリ エディターを登録する必要があります。
カテゴリ エディターをカプセル化および登録するには
TextCategoryEditor という名前の新しいクラスを CustomControlLibrary.Design プロジェクトに追加します。
TextCategoryEditor のコード エディターで、自動的に生成されたコードを次のコードに置き換えます。
namespace CustomControlLibrary.Design { using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using Microsoft.Windows.Design.PropertyEditing; public class TextCategoryEditor : CategoryEditor { private EditorResources res = new EditorResources(); public TextCategoryEditor() { } public override bool ConsumesProperty(PropertyEntry property) { return true; } public override DataTemplate EditorTemplate { get { return res["TextCategoryEditorTemplate"] as DataTemplate; } } public override object GetImage(Size desiredSize) { return null; } public override string TargetCategory { get { return "Text"; } } } }
Metadata という名前の新しいクラスを CustomControlLibrary.Design プロジェクトに追加します。
Metadata のコード エディターで、自動的に生成されたコードを次のコードに置き換えます。
using System; using System.Collections.Generic; using System.Text; using Microsoft.Windows.Design.Metadata; using System.ComponentModel; using Microsoft.Windows.Design.PropertyEditing; using System.Windows.Media; using System.Windows.Controls; using System.Windows; using CustomControlLibrary; // The ProvideMetadata assembly-level attribute indicates to designers // that this assembly contains a class that provides an attribute table. [assembly: ProvideMetadata(typeof(CustomControlLibrary.Design.Metadata))] namespace CustomControlLibrary.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(); builder.AddCustomAttributes (typeof(CustomControl1), new EditorAttribute( typeof(TextCategoryEditor), typeof(TextCategoryEditor))); return builder.CreateTable(); } } } }
ソリューションをビルドします。
カテゴリ エディターのテスト
これでカテゴリ エディターが完成し、使用できる状態になりました。 後はテストするだけです。 カテゴリ エディターをテストするには、WPF アプリケーションをプロジェクトに追加し、カスタム コントロールを WPF アプリケーションに追加して、カテゴリ エディターの動作を確認します。
カテゴリ エディターをテストするには
Visual C# の DemoApplication という名前の WPF アプリケーション プロジェクトをソリューションに追加します。
WPF デザイナーで MainWindow.xaml が開きます。
CustomControlLibrary プロジェクトへの参照を追加します。
MainWindow.xaml の XAML ビューで、自動的に生成された XAML を次の XAML に置き換えます。 この XAML により、CustomControlLibrary 名前空間への参照が追加され、CustomControl1 カスタム コントロールが追加されます。 現在デザイン モードであることを示すテキストと共に、ボタンがデザイン ビューに表示されます。 ボタンが表示されない場合は、デザイナーの一番上の情報バーをクリックして、ビューの再読み込みを行う必要があります。
<Window x:Class="DemoApplication.MainWindow" xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="300" Width="300" xmlns:my="clr-namespace:CustomControlLibrary;assembly=CustomControlLibrary"> <Grid> <my:CustomControl1 Margin="30,30,30,30" Name="customControl11"></my:CustomControl1> </Grid> </Window>
デザイン ビューでコントロールを選択します。
[プロパティ] ウィンドウで、Text カテゴリを見つけます。
他のコントロールとは異なる、テキスト プロパティを指定するユーザー インターフェイスが表示されていることを確認してください。 フォント名とフォント サイズをドロップダウン リストから選択できます。 チェック ボックスをオンにすると、太字と斜体を指定できます。
このカテゴリに含まれるプロパティを変更します。 変更内容がコントロールに反映されます。