試してみよう: カスタム プロパティを持つカスタム コントロールの作成
Blend for Visual Studio には、アプリケーションで使用できるさまざまなシステム コントロールやスタイルが用意されています。 これらのコントロールやスタイルが特定の要件に適合しない場合は、カスタム コントロールを作成できます。カスタム コントロールを作成するには、いずれかの System.Windows.Controls クラスから継承する Microsoft .NET クラスを作成します。
イメージを表示するためにイメージ ファイルのパスを保持する新しいプロパティを含むカスタム ボタン コントロールを作成する手順を次に示します。
カスタム プロパティを持たないユーザー コントロールをコードを使わずに作成する例については、「Blend での空のユーザー コントロールの作成」を参照してください。
XAML とコード例を含むカスタム コントロールの詳細については、MSDN の「Windows Presentation Foundation」の「コントロールの作成の概要」および「DependencyProperty Class (DependencyProperty クラス)」を参照してください。
カスタム コントロールを定義するには
[プロジェクト] パネルで Window1.xaml ファイルを展開して、プロジェクトの分離コード ファイル (Window1.xaml.cs ) を表示します (プロジェクトを作成するときに言語として Microsoft Visual Basic を選択すると、分離コード ファイル名は Window1.xaml.vb になります)。 分離コード ファイルをダブルクリックして開き、編集します。
Window1.xaml.cs ファイルで、ファイルの最後にある閉じかっこ (}) の直前に、次のクラス定義のソース コードを貼り付けます (Visual Basic では、End Namespace の直前または最後の End Class の直後に、適切なコードを貼り付けます)。
public class ImageButton : Button { public ImageSource Source { get { return base.GetValue(SourceProperty) as ImageSource; } set { base.SetValue(SourceProperty, value); } } public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageButton), null); }
Class ImageButton Inherits Button Public Property Source() As ImageSource Get Return CType(MyBase.GetValue(SourceProperty), ImageSource) End Get Set(ByVal value As ImageSource) MyBase.SetValue(SourceProperty, value) End Set End Property Public Shared ReadOnly SourceProperty As DependencyProperty = DependencyProperty.Register("Source", GetType(ImageSource), GetType(ImageButton), nothing) End Class
変更した分離コード ファイルを保存して閉じます。
ヒント
ImageButton クラスは、依存関係プロパティのパターンを示したものです。外部的に、このクラスは、ImageSource 型の Source という名前の通常の共通言語ランタイム (CLR、つまり .NET) プロパティを公開します。また、SourceProperty という読み取り専用の依存関係プロパティ フィールドも登録して公開し、依存関係プロパティに関して Source プロパティ用に CLR アクセサーを実装します。依存関係プロパティで登録することで、WPF または Silverlight による多様なサービスを利用できるようになります。提供できるサービスには、スタイル設定、データ バインディング、値の継承、既定値、アニメーションなどがあります。コントロール テンプレート内からプロパティ値にバインドするテンプレートのバインドという機能もあります。このチュートリアルでは、実行中のテンプレートのバインドについて説明します。
ヒント
カスタム コントロールのクラス定義のソース コードを、別のソース コード ファイルに保存することもできます。上記の 2 つの手順の代わりに、ImageButton.cs という新しいファイルを作成し、ソース コード、名前空間の宣言、およびドキュメントの分離コード ファイルの using ディレクティブの同じセットをこのファイルに貼り付け、新しいファイルをプロジェクトに追加することもできます ([プロジェクト ] メニューの [アイテムの追加] をクリックします)。
新しい ImageButton コントロールが [アセット] パネルに表示されるようにプロジェクトを構築する必要があります。 Blend の [プロジェクト] メニューの [プロジェクトのビルド] をクリックするか、または Ctrl キーと Shift キーを押しながら B キーを押します。 エラーが発生せずにビルドが完了することを確認します。
Blend での Window1.xaml の編集作業に戻ります。
Blend の左側に表示される [ツール] パネルで、[アセット] をクリックします。
[アセット] パネルが開き、ドキュメントに配置できるすべてのコントロール、パネル、およびオブジェクトが表示されます。
[プロジェクト] タブで [ImageButton] コントロールを選択します。
[ツール] パネルの [アセット] ボタンの下に、指定した ImageButton コントロールのアイコンが選択された状態で表示され、アートボードにこのコントロールを描画できるようになります。
注意
カスタム コントロールを [アセット] パネルの [プロジェクト] カテゴリに表示するには、プロジェクトにソース コードを追加してビルドする (Ctrl + Shift + B キー) 必要があります。
ImageButton を描画するには、[ツール] パネルで ImageButton アイコンを選択した状態で、アートボードをクリックし、ドキュメント内に境界ボックスを描画します。
ImageButton がアートボードにレンダリングされ、[ImageButton] "ImageButton" という名前の ImageButton オブジェクトが LayoutRoot の子オブジェクトとして [オブジェクトとタイムライン] パネルに表示されます。
カスタム コントロールのスタイルを変更するには
すべての ImageButton 要素のコントロール テンプレートを作成するには、新しい ImageButton を右クリックし、[テンプレートの編集] をクリックして、[コピーして編集] をクリックします。
[スタイル リソースの作成] ダイアログ ボックスが表示されます。
[スタイル リソースの作成] ダイアログ ボックスの [リソース名 (キー)] フィールド (最初のオプション ボタンの横にあるテキスト ボックス) に、「ImageButtonStyle」と入力します。
リソース ディクショナリのテンプレートに名前が設定されます。これで、任意の ImageButton オブジェクトに対してテンプレートとして設定できます。
注意
コントロールに適用されるスタイルがコントロールの外観 (パーツ) と動作の両方を含むよう、コントロール テンプレートはスタイルの内部にラップされています。
[定義元] フィールドで [このドキュメント] オプション ボタンをオンにし、ドロップダウン リストで [Window: Window] が選択されていることを確認します。
[定義先] フィールドには、新しいテンプレートをどのリソース ディクショナリ内で定義するかが表示されます。 [Window: Window] を選択すると、ウィンドウ内のすべての ImageButton コントロールからテンプレートを認識できることを意味します。
[OK] をクリックします。
これで、すべての ImageButton オブジェクトの既定のコントロールがコピーされ、コピーが ImageButtonStyle という新しい ControlTemplate として保存されました。 新しいテンプレートがリソース ディクショナリに配置されています。このテンプレートは、[リソース] パネルの [Window] ノードで確認できます。
新しいテンプレートを作成すると、Blend は、新しいテンプレートを表示および編集できるモードになります。 [オブジェクトとタイムライン] パネルにある新しいオブジェクト ツリーの上の "テンプレート" という語は、編集している現在のスコープを示します。 テンプレートには、このテンプレートを使用する ImageButton の Content プロパティ値を自動的に表示する ContentPresenter オブジェクトが含まれます。
ヒント
テンプレートの編集モードを終了してドキュメントのスコープに戻るには、オブジェクト ツリーの上の ImageButtonStyle の横にある [上へスコープ] をクリックします。
既存のテンプレートを編集するためにテンプレートの編集モードに戻るには、[オブジェクトとタイムライン] パネルでテンプレートを編集するオブジェクト (この例では [ImageButton] "ImageButton" オブジェクト) を右クリックし、[テンプレートの編集] をクリックして、[現在のテンプレートの編集] をクリックします。
[オブジェクトとタイムライン] パネルで ContentPresenter オブジェクトを右クリックし、[グループ化設定] をポイントして Grid をクリックします。
ContentPresenter オブジェクトが新しい Grid オブジェクトの子オブジェクトになります。 Grid オブジェクトが存在しない場合、2 つ目の子オブジェクトをテンプレートに追加することはできません。クロム オブジェクトには 1 つの子オブジェクトしか含めることができないためです。
[オブジェクトとタイムライン] パネルで Grid オブジェクトを選択した状態で、[プロパティ] パネルの [レイアウト] カテゴリにある [Width] と [Height] のプロパティを見つけます。 各プロパティの横にある [詳細オプション] をクリックし、[リセット] をクリックします。
グリッドを 2 つの列に分割するには、[オブジェクトとタイムライン] パネルで Grid オブジェクトをダブルクリックしてアクティブにし、[ツール] パネルで [選択内容] ツール をクリックして、アートボードの Grid の上部にある濃い青のルーラーにマウス ポインターを移動します。 オレンジ色の列ルーラーがマウス ポインターに従って移動します。このルーラーは、クリックしたときに新しい列デバイダを配置する場所を示します。
クリックすると、Grid の途中で新しい列区切り線が作成されます。
青の列区切り線が Grid 内に表示されます。
[アセット] パネルの [コントロール] カテゴリから [イメージ] を選択します ([すべて] サブカテゴリをクリックします)。 Grid オブジェクトが [オブジェクトとタイムライン] パネルでアクティブなままの状態で、Grid の右側の列の中に新しい Image を描画します。
[オブジェクトとタイムライン] パネルで新しい Image オブジェクトが選択された状態で、[プロパティ] パネルの [共通プロパティ] の下に移動します。 Source プロパティの右にある [詳細オプション] をクリックし、[テンプレートのバインド] をポイントして、[Source] をクリックします。
これで、Image の Source テンプレートが、このテンプレートを使用する ImageButton の Source プロパティにテンプレート バインドされました。
テンプレートの編集は完了しました。 ルート オブジェクトのスコープに戻るには、[オブジェクトとタイムライン] パネルで [スコープを <オブジェクト名> に戻す] をクリックします。
[オブジェクトとタイムライン] パネルで ImageButton を選択した状態で、[プロパティ] パネルの [その他] カテゴリにある Source プロパティを見つけます。このプロパティに、コンピューター上のイメージ ファイルのパスを設定します。
イメージが ImageButton コントロールの右側に表示されます。
他のカスタム コントロールにスタイルを適用するには
[アセット] パネルの [プロジェクト] カテゴリで、ImageButton コントロールを選択します。 アートボード上に新しい ImageButton コントロールを描画します。
描画した ImageButton を右クリックし、[テンプレートの編集] をクリックして、[リソースの適用] をクリックします。次に、ImageButtonStyle というスタイル名をクリックします。
ImageButtonStyle が新しい ImageButton コントロールに適用されます。 [プロパティ] パネルの [その他] カテゴリで Source プロパティを検索し、コンピューター上のイメージ ファイルのパスを設定します。
ヒント
代わりに、テンプレートを使用して既にスタイルが適用されている ImageButton をアートボードに追加することもできます。[アセット] パネルの [スタイル] カテゴリで ImageButtonStyle を選択した後、スタイルを適用した ImageButton をアートボードに描画します。
カスタム プロパティに説明を付けるには
分離コード ファイル (Window1.xaml.cs) の先頭に、System.ComponentModel 名前空間への参照を追加します。
以下で使用する説明属性とカテゴリ属性は、この名前空間で定義されています。
クラス定義の前に、次の行 (太字) を貼り付けます。
[Description("Represents a custom button control that responds to a Click event. Displays an image using a custom Source property if the Source property is bound to an Image in the template.")] public class ImageButton : Button
<Description("Represents a custom button control that responds to a Click event. Displays an image using a custom Source property if the Source property is bound to an Image in the template.")> _ Class ImageButton
カスタム プロパティ定義の前に、次の行 (太字) を貼り付けます。
[Description("The image displayed in the button if there is an Image control in the template whose Source property is template-bound to the ImageButton Source property."), Category("Common Properties")] public ImageSource Source
<Description("The image displayed in the button if there is an Image control in the template whose Source property is template-bound to the ImageButton Source property."), Category("Common Properties")> _ Public Property Source() As ImageSource
Category 属性は、[プロパティ] パネルでプロパティを表示する場所を構成します。
Ctrl + Shift + B キーを押して、プロジェクトをリビルドします。
ImageButton の Source プロパティが [プロパティ] パネルの [共通プロパティ] カテゴリに表示されるようになり、[アセット] パネルのプロパティおよびコントロールの上にマウス ポインターを移動すると、ツールヒントに説明が表示されます。
コントロールをアートボードに描画するとき、したがってデザイン モードのときにプロパティを既定値に設定するコードを、カスタム コントロールのコンストラクターに追加できます。 次の手順を使用して設定するプロパティは、アートボードでの表示に対してのみ適用され、アプリケーションの実行時の表示には適用されません。 コンテンツがデータベースや Web サービスから取得される場合など、デザイン モードのときにはコントロールのコンテンツを利用できず、アプリケーションの実行時には利用できる場合に役に立ちます。 この場合、アートボード上の ImageButton の Source プロパティは、明示的に設定されるまでは、プロジェクトのイメージ ファイルの名前に設定されます。
既定のイメージを表示するコントロールを構成するには
分離コード ファイル (Window1.xaml.cs) で、プロパティ定義の後に、次のコード行 (太字) を貼り付けます。
注意
次のコードのファイル名 (Sunset.jpg) を、実際のプロジェクトでのイメージ ファイルの名前に変更してください。プロジェクトにイメージ ファイルを追加するには、[プロジェクト] パネルでプロジェクト名を右クリックし、[既存のアイテムを追加] をクリックします。
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register("Source", typeof(ImageSource), typeof(ImageButton)); // Constructor: public ImageButton() { if (DesignerProperties.GetIsInDesignMode(this)) { this.Source = new BitmapImage(new Uri("Sunset.jpg", UriKind.Relative)); } }
Public Shared ReadOnly SourceProperty As DependencyProperty = DependencyProperty.Register("Source", GetType(ImageSource), GetType(ImageButton)) Public Sub New() If DesignerProperties.GetIsInDesignMode(Me) Then Me.Source = New BitmapImage(New Uri("Sunset.jpg", UriKind.Relative)) End If End Sub
Ctrl + Shift + B キーを押して、プロジェクトをリビルドします。
作成したスタイルを使用するアートボードに ImageButton を追加すると、ボタンに既定のイメージが表示されるようになります。
注意
デザイン モードでは、Source プロパティに他の値を設定することはできません。