「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>XAML]]
--XAMLの書き方(1)
--[[XAMLの書き方(2)]]

* 目次 [#i78ae0d5]
#contents

*概要 [#d37660b8]
基本的なXAMLの書き方。

*名前空間 [#x46c4d22]
XAMLにおける各種の名前空間の宣言は、xmlns属性を使用したXML名前空間にて行う。~
ここでは、以下の既定の名前空間の宣言を例にとって説明する。

-名前空間の宣言
 <Window x:Class="WpfApplication1.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

-XML名前空間の簡単な説明~
http://www.kanzaki.com/docs/sw/names.html

**WPF名前空間 [#u9e59dba]
2行目のXML名前空間の宣言(xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation")では、~
WPFフレームワーク(PresentationFramework.dll)のアセンブリ内に同梱されるURIにマップされた~
CLR名前空間(System.Windows.Controls、System.Windows.Dataなど)を、既定のXML名前空間(プレフィックスなし)として割り当てている。~
そのため、既定でXAMLからWPFフレームワークのCLRオブジェクトを利用できる。

**XAML名前空間 [#f7e47ba4]
3行目のXML名前空間の宣言(xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml")では、~
URIにマップされた共通的なXAMLの言語機能がXML名前空間(x)として割り当てられている。~
これにより、「x:」というプレフィックスを使用することで、「[[言語機能>#ad009a58]]」で説明する、XAMLの言語機能を使用できるようになる。

**CLR名前空間 [#b9a3d659]
CLR名前空間について以下を例にとって説明する。

***(1) [#j611ebcc]

-CLR名前空間の宣言
 <Window x:Class="WpfApplication1.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:igDP="http://infragistics.com/DataPresenter" <--- 名前空間の宣言(追加
   Title="Window1" Height="300" Width="300">
   <Grid>
     <igDP:XamDataGrid Name="xamDataGrid1"/> <--- 名前空間の使用例
   </Grid>
 </Window>

Infragistics社製のNetAdvantageなど、

>XmlnsDefinitionアセンブリ属性でURIとCLR名前空間のマップが指定された~
サードパーティ製のUIコンポーネントをD&DでVSデザイナから追加した場合、~

上記の例のように自動的にXML名前空間の宣言が追加される。

-MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Markup.XmlAttributeProperties.XmlnsDefinitionプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.markup.xmlattributeproperties.xmlnsdefinition.aspx

なお、XML名前空間には一意の名前を自由に付与でき(上記の例ではigDP)、~
このプレフィックスを使用することで、XAMLからUIコンポーネントのCLRオブジェクトを利用できる。

***(2) [#y81abbb2]
この他に、URIとしてCLR名前空間とアセンブリを直接指定する方法もある。

-CLR名前空間の宣言
 xmlns:sys="clr-namespace:(CLR名前空間);assembly=(アセンブリ名)"
--例1:サードパーティ製品
 <Window x:Class="WpfApplication1.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:igDP="clr-namespace:Infragistics.Windows.DataPresenter;assembly=Infragistics3・・・" <--- 名前空間の宣言
   Title="Window1" Height="300" Width="300">
   <Grid>
     <igDP:XamDataGrid Name="xamDataGrid1"/> <--- 名前空間の使用例
--例2:.NET Framework
 <Window x:Class="WpfApplication1.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:sys="clr-namespace:System;assembly=mscorlib" <--- 名前空間の宣言
   Title="Window1" Height="300" Width="300">
   <Window.Resources>
     <x:Array x:Key="List" Type="{x:Type sys:String}"> <--- 名前空間の使用例
--例3:自作の同一プロジェクトのクラス
 <Window x:Class="WpfApplication1.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:uc="clr-namespace:WpfApplication1" <--- 名前空間の宣言
   Title="Window1" Height="300" Width="300">
   <StackPanel Orientation="Vertical">
     <uc:UserControl1 x:Name="userControl1"/> <--- 名前空間の使用例

-この方法では、「clr-namespace」、「assembly」などの定義済みトークンを使用する。
--当該プロジェクト中のCLR名前空間を指定する場合は、「assembly」トークンは省略できる。
--XML名前空間には一意の名前を自由に付与でき、このプレフィックスを使用することで、XAMLからUIコンポーネントのCLRオブジェクトを利用できる。

-製品並みのカスタムのUIコントロールを開発・使用するなどの目的を除いて、CLRクラスを開発しXAMLから使用する場合、
--一般的には「clr-namespace、assembly」の定義済みトークンを使用する。
--ただし、この方法は、1つのCLR名前空間に対して、1つのXML名前空間しか割り当てられない
--(XmlnsDefinitionアセンブリ属性を使用すると、1つのXML名前空間に複数のCLR名前空間を割り当てられる)。

***参考 [#v51c1b09]
-MSDN > WPFの基礎 > WPFのXAML > XAML名前空間およびWPF XAMLの名前空間の割り当て~
http://msdn.microsoft.com/ja-jp/library/ms747086.aspx

*言語機能 [#ad009a58]
XAMLの言語機能である
-「[[ディレクティブ>#j78f478c]]」
-「[[マークアップ拡張>#b565ab69]]」

について説明する。

-MSDN > .NET Framework XAMLサービスの概念説明のドキュメント > XAML名前空間 (x:) 言語機能~
http://msdn.microsoft.com/ja-jp/library/ms753327.aspx

**ディレクティブ [#j78f478c]
XAMLの言語機能が提供する各種ディレクティブについて説明する。

|項番|ディレクティブ|説明|h
|~|~|例|h
|1|x:Class|XAML上から分離クラス(コード ビハインド)のクラス名を定義する。|
|~|~|<Window x:Class="WpfApplication1.Window1"|
|2|x:Subclass|パーシャル クラスをサポートしない言語で使用する。通常は利用しない。|
|~|~|-|
|3|x: ClassModifier|クラスのアクセスレベルを変更する。通常は利用しない。|
|~|~|-|
|4|x:Code|XAML上にインラインコードを実装する場合に使用する。通常は利用しない。|
|~|~|<Grid>&br;&nbsp;&nbsp;<x:Code>&br;&nbsp;&nbsp;&nbsp;&nbsp;<![CDATA[&br;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;button1_Click(object&nbsp;sender,&nbsp;RoutedEventArgs&nbsp;e)&nbsp;{&br;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;button1.Content&nbsp;=&nbsp;"Hello&nbsp;World";&br;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&br;&nbsp;&nbsp;&nbsp;&nbsp;]]>&br;&nbsp;&nbsp;</x:Code>&br;&nbsp;&nbsp;<Button&nbsp;Name="button1"&nbsp;Click="button1_Click">Button</Button>&br;</Grid>|
|5|x:FieldModifier|プロパティのアクセスレベルを変更する。通常は利用しない。|
|~|~|-|
|6|x:Key|XAMLで定義された各種「[[リソース>#p50dd8ac]]」を識別する。下記は、x:Keyを使用して「[[スタイル>#v30d5ab6]]」の「[[リソース>#p50dd8ac]]」をボタンに「[[データ バインディング>#w4afa32c]]」する例。|
|~|~|<Window.Resources>&br;&nbsp;&nbsp;<Style&nbsp;x:Key="buttonStyle"&nbsp;TargetType="{x:Type&nbsp;Button}">&br;&nbsp;&nbsp;&nbsp;&nbsp;<Setter&nbsp;Property="Background"&nbsp;Value="LightYellow"&nbsp;/>&br;&nbsp;&nbsp;</Style>&br;</Window.Resources>&br;<Grid>&br;&nbsp;&nbsp;<Button&nbsp;Style="{StaticResource&nbsp;buttonStyle}">Hello&nbsp;Style</Button>&br;</Grid>|
|7|x:Name|XAMLで生成したCLRオブジェクトに名前を付与する。Name属性と差異は無い。|
|~|~|<Button&nbsp;x:Name="button1">&br;&nbsp;&nbsp;&nbsp;Click&nbsp;Here&br;</Button>|
|8|x:Shared|静的な[[リソース>#p50dd8ac]]を、取得の度に生成する場合に使用する。通常は利用しない。&br;※&nbsp;true&nbsp;:&nbsp;静的(全てのインスタンスは同じ)&br;&nbsp;&nbsp;&nbsp;false&nbsp;:&nbsp;動的(取得の度に生成する)&br;&nbsp;&nbsp;&nbsp;既定値&nbsp;:&nbsp;true|
|~|~|-|
|9|x:TypeArguments|ジェネリックの型引数をコンストラクタに渡す。&br;(.NET Framework 4.0のXAML 2009からのサポート)|
|~|~|<!--&nbsp;XAML&nbsp;2009&nbsp;-->&br;<ObservableCollection&nbsp;x:TypeArguments="Employee">&br;&nbsp;&nbsp;<l:Employee&nbsp;FirstName="John"&nbsp;Name="Doe"&nbsp;/>&br;&nbsp;&nbsp;<l:Employee&nbsp;FirstName="Tim"&nbsp;Name="Smith"&nbsp;/>&br;</ObservableCollection>|
|10|x:Uid|ローカライゼーションのプロセスとツールによって使用される一意識別子を指定する 。|
|~|~|-|
|11|xml:lang|カルチャ情報を宣言する。|
|~|~|<Window&nbsp;x:Class="WpfApplication1.Window1"&br;&nbsp;&nbsp;xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&br;&nbsp;&nbsp;xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&br;&nbsp;&nbsp;xml:lang="ja-JP"|

-MSDN > Windows Presentation Foundation > グローバライズとローカライズ > WPFのグローバリゼーション~
http://msdn.microsoft.com/ja-jp/library/ms745650.aspx

**マークアップ拡張 [#b565ab69]
XAMLの言語機能が提供する各種「マークアップ拡張」について説明する。~
通常、「マークアップ拡張」は、「{」と「}」の2つの中括弧を使用することでXAMLパーサに対し、拡張されたプロパティ指定方法を指示する。

-MSDN > WPFの基礎 > WPFのXAML
--> マークアップ拡張機能とWPF XAML~
http://msdn.microsoft.com/ja-jp/library/ms747254.aspx
--> WPF XAML拡張機能~
http://msdn.microsoft.com/ja-jp/library/ms747180.aspx

***XAMLで定義されたマークアップ拡張 [#ld42b6a9]
以下、XAMLの機能である「XAMLで定義されたマークアップ拡張」を一覧する。~
これらの種類は、中括弧+「x:」プレフィックスの直後の文字列トークンによって識別される。

-XAMLに実装されたマークアップ拡張
|項番|文字列トークン|説明|h
|~|~|例|h
|1|x:Static|静的プロパティ(定数、静的プロパティ、フィールド、列挙値)を参照する。&br;構文:<object property="{x:Static Member=prefix:typeName.staticMemberName}" .../>|
|~|~|<Button&nbsp;&br;&nbsp;&nbsp;&nbsp;&nbsp;Foreground="{x:Static&nbsp;Member=SystemColors.InfoTextBrush}"&br;&nbsp;&nbsp;&nbsp;&nbsp;Background="{x:Static&nbsp;Member=SystemColors.InfoBrush}">&br;&nbsp;&nbsp;Click&nbsp;Here&br;</Button>|
|2|x:Null|CLRオブジェクトのプロパティにnull値を設定する(既定値をnullクリアする場合など)。|
|~|~|<Button&nbsp;x:Name="button1"&nbsp;Background="{x:Null}"&nbsp;Click="button1_Click">&br;&nbsp;&nbsp;Click&nbsp;Here&br;</Button>|
|3|x:Type|CLRクラスの型情報を指定する。|
|~|~|詳しくは、下記、項番4の例を参照のこと。|
|4|x:Array|IEnumerableを持つArrayオブジェクト(配列)を生成する。|
|~|~|<Window.Resources>&br;&nbsp;&nbsp;<x:Array&nbsp;x:Key="List"&br;&nbsp;&nbsp;&nbsp;&nbsp;Type="{x:Type&nbsp;sys:String}">&br;&nbsp;&nbsp;&nbsp;&nbsp;<sys:String>A</sys:String>&br;&nbsp;&nbsp;&nbsp;&nbsp;<sys:String>B</sys:String>&br;&nbsp;&nbsp;&nbsp;&nbsp;<sys:String>C</sys:String>&br;&nbsp;&nbsp;</x:Array>&br;</Window.Resources>&br;<StackPanel>&br;&nbsp;&nbsp;<ListBox&nbsp;ItemsSource="{Binding&nbsp;Source={StaticResource&nbsp;List}}"/>&br;</StackPanel>&br;&br;※&nbsp;先頭で、.NET&nbsp;FrameworkのSystem名前空間のインポートが必要&br;&nbsp;&nbsp;&nbsp;xmlns:sys="clr-namespace:System;assembly=mscorlib"&br;&br;※&nbsp;StaticResourceについては次項で説明する。|

※ x:Arrayは、例外的に中括弧と共に使用しない。

***WPF固有のマークアップ拡張 [#dbf77234]
以下、WPF の機能である「WPF固有のマークアップ拡張」を一覧する。~
こちらは、プロパティ値に「[[データ バインディング>#w4afa32c]]」や、「[[リソース>#p50dd8ac]]」への参照を指定できる。

-XAMLに実装されたマークアップ拡張
|項番|文字列トークン|説明|h
|~|~|構文 ※ 「[[プロパティ属性構文>#tb0bd2e6]]」と「[[プロパティ要素構文>#s389a559]]」については、後述する。|h
|1|{Binding&br;・・・|Bindingオブジェクトに「バインディング ターゲット」のプロパティを設定することで、「[[データ バインディング>#w4afa32c]]」を実装する。&br;MSDN > WPFの基礎 > WPFのXAML > WPF XAML拡張機能 > バインディングのマークアップ拡張機能&br;http://msdn.microsoft.com/ja-jp/library/ms750413.aspx|
|~|~|具体例は、「[[データ バインディングの基礎>#h0ae3316]]」を参照のこと。|
|2|{StaticResource&br;・・・|既に定義された[[リソース>#p50dd8ac]]に対する参照を検索し、任意のXAMLプロパティ属性の値を設定する。|
|~|~|具体例は、「[[リソースとのデータ バインディング>#eb81566f]]」を参照のこと。&br;&br;[[プロパティ属性構文>#tb0bd2e6]]:&br;<object&nbsp;property="{StaticResource&nbsp;key}"&nbsp;.../>&br;&br;なお、「[[データ バインディング>#w4afa32c]]」で使用する場合は、次のようになる。&br;<object&nbsp;property="{Binding&nbsp;Source={StaticResource&nbsp;key}&nbsp;...}"&nbsp;.../>&br;&br;[[プロパティ要素構文>#s389a559]]:&br;<object>&br;&nbsp;&nbsp;<object.property>&br;&nbsp;&nbsp;&nbsp;&nbsp;<StaticResource&nbsp;ResourceKey="key"&nbsp;.../>&br;&nbsp;&nbsp;</object.property>&br;</object>|
|3|{DynamicResource&br;・・・|[[リソース>#p50dd8ac]]が変化したときに、任意のXAMLプロパティ属性の値を設定する。&br;keyには、x:Key属性によって指定された既存の「[[リソース>#p50dd8ac]]」に対応するキーを指定する。|
|~|~|具体例は、「[[リソースとのデータ バインディング>#eb81566f]]」を参照のこと。&br;&br;[[プロパティ属性構文>#tb0bd2e6]]:&br;<object&nbsp;property="{DynamicResource&nbsp;key}"&nbsp;.../>&br;&br;なお、「[[データ バインディング>#w4afa32c]]」で使用する場合は、次のようになる。&br;<object&nbsp;property="{Binding&nbsp;Source={DynamicResource&nbsp;key}&nbsp;...}&nbsp;"&nbsp;.../>&br;&br;[[プロパティ要素構文>#s389a559]]:&br;<object>&br;&nbsp;&nbsp;<object.property>&br;&nbsp;&nbsp;&nbsp;&nbsp;<DynamicResource&nbsp;ResourceKey="key"&nbsp;.../>&br;&nbsp;&nbsp;</object.property>&br;</object>|
|4|{TemplateBinding&br;・・・|親コントロールに適用したプロパティ値を「[[テンプレート>#o64ea160]]」に反映させる。&br;MSDN > WPFの基礎 > WPFのXAML > WPF XAML拡張機能 > TemplateBindingのマークアップ拡張機能&br;http://msdn.microsoft.com/ja-jp/library/ms742882.aspx|
|~|~|具体例は、「[[テンプレート>#o64ea160]]」を参照のこと。&br;&br;[[プロパティ属性構文>#tb0bd2e6]]:&br;<object property="{TemplateBinding TargetProperty }" .../>|
|5|{RelativeSource&br;・・・|Binding.RelativeSourceを指定する。詳しくは、下記のURLを参照のこと。&br;また、[[次>#b35e6e76]]で例を挙げて説明する。&br;&br;MSDN > WPFの基礎 > WPFのXAML > WPF XAML拡張機能 > RelativeSourceのマークアップ拡張機能&br;http://msdn.microsoft.com/ja-jp/library/ms743599.aspx|
|~|~|具体例は、[[次>#b35e6e76]]を参照のこと。&br;&br;[[プロパティ属性構文>#tb0bd2e6]]:&br;<Binding&nbsp;RelativeSource="{RelativeSource&nbsp;modeEnumValue}"&nbsp;.../>&br;&br;なお、「[[データ バインディング>#w4afa32c]]」で使用する場合は、次のようになる。&br;<object&nbsp;property="{Binding&nbsp;RelativeSource={RelativeSource&nbsp;modeEnumValue}&nbsp;...}"&nbsp;.../>&br;&br;[[プロパティ要素構文>#s389a559]]:&br;<Binding>&br;&nbsp;&nbsp;<Binding.RelativeSource>&br;&nbsp;&nbsp;&nbsp;&nbsp;<RelativeSource&nbsp;Mode="modeEnumValue"/>&br;&nbsp;&nbsp;</Binding.RelativeSource>&br;</Binding>&br;&nbsp;OR&nbsp;&br;<Binding>&br;&nbsp;&nbsp;<Binding.RelativeSource>&br;&nbsp;&nbsp;&nbsp;&nbsp;<Relative&br;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Mode="FindAncestor"&br;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AncestorType="{x:Type&nbsp;typeName}"&br;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AncestorLevel="intLevel"/>&br;&nbsp;&nbsp;</Binding.RelativeSource>&br;</Binding>|
|6|{ThemeDictionary&br;・・・|カスタム コントロールの作成者やサードパーティ製のUIコンポーネントの、&br;コントロールの「[[スタイル>#v30d5ab6]]」をアプリケーションの「[[リソース>#p50dd8ac]]」から読み込む。&br;&br;MSDN > WPFの基礎 > WPFのXAML > WPF XAML拡張機能 > ThemeDictionaryのマークアップ拡張機能&br;http://msdn.microsoft.com/ja-jp/library/ms752067.aspx|
|~|~|-|

※ keyには、x:Keyディレクティブによって指定された既存の[[リソース>#p50dd8ac]]に対応するキーを指定する。

**マークアップ拡張の例 [#xa799e4b]
***バインディングのマークアップ拡張の例 [#vec851f2]
[[こちら>#ca5673d9]]

***TemplateBindingの例 [#hee73def]
[[こちら>#wc88b865]]

***RelativeSourceの例 [#b35e6e76]
[[こちら>#wc88b865]]

*プロパティの設定方法 [#ra4d77a1]
プロパティの設定方法として、
-[[プロパティ属性構文>#tb0bd2e6]]:~
要素の属性にテキストを使用して設定する。
-[[プロパティ要素構文>#s389a559]]:~
要素のinnerText・innerXMLを使用してプロパティを設定する。

の2つの構文について説明する。

以下、TextBox要素に対して、同等の属性を設定する~
「[[プロパティ属性構文>#tb0bd2e6]]」と「[[プロパティ要素構文>#s389a559]]」の例を示す。

**プロパティ属性構文 [#tb0bd2e6]
要素の属性にテキストを使用してプロパティを設定する方法

-プロパティ属性構文の例
 <TextBox 
    Width = "100"
    FontSize = "30"
    Text = "text1"
    Background = "White"
    Foreground = "Blue" />

**プロパティ要素構文 [#s389a559]
要素のinnerText・innerXMLを使用してプロパティを設定する方法

-プロパティ要素構文の例
 <TextBox>
   <TextBox.Width>100</TextBox.Width>
   <TextBox.FontSize>30</TextBox.FontSize>
   <TextBox.Background>
     <SolidColorBrush Color="White"/>
   </TextBox.Background>
   <TextBox.Foreground>
     <SolidColorBrush Color="Blue"/>
   </TextBox.Foreground>
   <TextBox.Text>text1</TextBox.Text>
 </TextBox>

なお、子要素のコレクションを設定する「[[プロパティ要素構文>#s389a559]]」である
-Panel.Childrenプロパティ
-ItemsControl.[[Itemsプロパティ>#v7960713]]

などは、暗黙的に使用されるため明記が不要のものもある。

**型コンバータ [#r36d6abd]
XAMLパーサは、XAMLの「[[プロパティ属性構文>#tb0bd2e6]]」として指定された各属性テキストを、~
プリミティブ型に変換できるリテラル文字列として解釈するか、「型コンバータ」を使用してオブジェクトに変換する。

なお、「型コンバータ」(と、そのベース クラスであるTypeConverterクラス)は、~
.NETのコンポーネントとコントロールのデザイン時・実行時の動作を実装する一般的なクラスであり、WPF独自のクラスではない。~
しかし、XAMLの「[[プロパティ属性構文>#tb0bd2e6]]」からのCLRプロパティ設定を多用するWPF / Silverlight開発では、その存在を認識しておいたほうが良い。

XAMLパーサは通常、プロパティの型(CLRクラス)にTypeConverterAttribute属性 が付与されているかを調べる。~
付与されている場合は、この属性値に基づいた「型コンバータ」を使って、TypeConverter.ConvertFromメソッド により文字列をプロパティ値に変換する。

以下は、ユーザ コントロールに、MyPointというカスタムの型を取るCLRプロパティを実装しXAMLに公開、~
XAMLの「[[プロパティ属性構文>#tb0bd2e6]]」として指定された各属性テキストを、カスタムの型に変換する「型コンバータ」を実装した例である。

***カスタム型 [#p2ae99f0]
MyPointというカスタム型(型コンバータを実装)

 /// <summary>
 /// カスタム型(型コンバータを実装)
 /// </summary>
 [TypeConverter(typeof(MyPointConverter))]
 public class MyPoint {
   public MyPoint(int x, int y) {
     this._x = x;
     this._y = y;
   }
   private int _x;
   public int X {
     set { this._x =value; }
     get { return this._x; } 
   }
   private int _y;
   public int Y {
     set { this._y = value; }
     get { return this._y; }
   }
 }

***型コンバータ [#k0c10e95]
 /// <summary>カスタム型の型コンバータ</summary>
 public class MyPointConverter : TypeConverter {
 
   /// <summary>CanConvertFrom(変換可能かチェックする)</summary>
   public override bool CanConvertFrom(
     ITypeDescriptorContext context, Type sourceType) {
     if (sourceType == typeof(string)) {
       return true;
     }
     return base.CanConvertFrom(context, sourceType);
   }
 
   /// <summary>指定された文字列をカスタム型(MyPoint)に変換する</summary>
   public override object ConvertFrom(
     ITypeDescriptorContext context,
     CultureInfo culture, object value) {
     if (value is string) {
       string[] v = ((string)value).Split(new char[] { ',' });
       return new MyPoint(int.Parse(v[0]), int.Parse(v[1]));
     }
     return base.ConvertFrom(context, culture, value);
   }
 
   /// <summary>指定されたカスタム型(MyPoint)を文字列に変換する</summary>
   public override object ConvertTo(ITypeDescriptorContext context,
     CultureInfo culture, object value, Type destinationType) {
     if (destinationType == typeof(string)) {
       return ((MyPoint)value).X + "," + ((MyPoint)value).Y;
     }
     return base.ConvertTo(context, culture, value, destinationType);
   }
 }

***ユーザ コントロール [#gc3459c6]
MyPointというカスタム型のCLRプロパティを実装

 /// <summary>
 /// UserControl1.xaml の相互作用ロジック
 /// </summary>
 public partial class UserControl1
   : UserControl {
   // CLRプロパティの定義(XAML属性に公開可能)
   private MyPoint _myLocation;
 
   public MyPoint MyLocation {
     set { this._myLocation = value; }
     get { return this._myLocation; }
   }
 
 ・・・

***型コンバータの使用例 [#gc5dd259]
上記のユーザ コントロールのカスタムの型を取るCLRプロパティを、以下のようにXAMLの「[[プロパティ属性構文>#tb0bd2e6]]」として指定された各属性テキストから初期化できる。

 <uc:UserControl1 x:Name="userControl1" MyLocation="10,20"/>

ただし、(当然ながら、)文字列からの変換をサポートしているだけで、すべてのプロパティ値をサポートすることはできない。~
文字列で表現できないプロパティ値は、「[[プロパティ属性構文>#tb0bd2e6]]」ではなく「[[プロパティ要素構文>#s389a559]]」として記述する方法を取る。

-MSDN > WPFの基礎 > WPFのXAML > TypeConverters及びXAML~
http://msdn.microsoft.com/ja-jp/library/aa970913.aspx

*コンテンツ構文 [#m4c088a5]
「コンテンツ構文」とは、[[Contentプロパティ>#gc84bde8]](または[[Itemsプロパティ>#v7960713]])に要素を設定する構文である。

-ContentPropertyAttributeを付けることで、

--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Markup.ContentPropertyAttributeクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.markup.contentpropertyattribute.aspx
---[ContentPropertyAttribute("Content")]→ [[Contentプロパティ>#gc84bde8]]
---[ContentPropertyAttribute("Items")]→ [[Itemsプロパティ>#v7960713]]
---[ContentPropertyAttribute("Content")] →  [[Contentプロパティ>#gc84bde8]]
---[ContentPropertyAttribute("Items")] →  [[Itemsプロパティ>#v7960713]]

-属性に指定される[[Contentプロパティ>#gc84bde8]]を、~
innerText・innerXML([[プロパティ要素構文>#s389a559]])として記述できるようになる。

--コンテンツ構文
---[[プロパティ属性構文>#tb0bd2e6]]
 <Button Content="Click Here" />
---[[プロパティ要素構文>#s389a559]]
 <Button>Click Here</Button>

-比較
--なお、[[Windows Forms]]や[[Web Forms>ASP.NET Web Forms]](HTML)などで、UIコントロールの表示のカスタマイズをするには、~
UIコントロールの「[[スタイル>#v30d5ab6]]」属性の指定による方法のみサポートされていた。
--これに対し、WPFのUIコントロールは「[[スタイル>#v30d5ab6]]」属性の指定による方法だけでなく、~
[[Contentプロパティ>#gc84bde8]](または[[Itemsプロパティ>#v7960713]])に任意の型の子要素を設定することができるため、~
コントロールの「外観」を自由に変更でき、柔軟性が非常に高くなっている。

-補足:Windowsフォームの外観の変更
--コントロールを自前で描画する「オーナー描画」と呼ばれる方法が用意されていたが、~
「オーナー描画」はグラフィックス メソッドなどを使用して、~
すべての描画を独自に行わなければならないため、深い知識と多量のコードが必要であった。

--関連資料
---[[.NETコントロールのカスタマイズ方法]]

**Contentプロパティ [#gc84bde8]
WPFのContentControlは、Contentプロパティに任意の型の子要素を設定することができるため、コントロールの「外観」を自由に変更できる。
WPFのContentControlは、
-ContentControl.Contentプロパティに設定された単一の要素を表示するという機能を提供するコントロール
-ContentControl.Contentプロパティに任意の型の子要素を設定することができるため、コントロールの「外観」を自由に変更できる。
-従って、ContentControlを継承するButtonクラスやLabelクラスなどなどではコントロールの「外観」を自由に変更できる。
--Control.Templateプロパティ
--ContentControl.ContentTemplateプロパティ

***文字列のコンテンツ要素を格納 [#m12672f2]

ContentControlのButtonコントロールを例にしてContentプロパティへ要素を設定する例を示す。
WPFのContentControlのButtonコントロールを例にしてContentプロパティへ要素を設定する例を示す。

-XAML
--[[プロパティ属性構文>#tb0bd2e6]]:
 <Button Width="200" Height="200" Content="ボタン"/>
--[[プロパティ要素構文>#s389a559]]:
 <Button Width="200" Height="200">ボタン</Button>
-レンダリング結果
#ref(ContentString.png,left,nowrap,文字列のコンテンツ要素を格納)

***イメージのコンテンツ要素を格納 [#faf81a9f]
Contentプロパティには、Imageオブジェクトなどの任意の型の要素も設定できる。

-XAML
 <Button Width="200" Height="200">
   <Button.Content>
     <Image Source=".\Blue hills.jpg"/>
   </Button.Content>
 </Button>

-レンダリング結果
#ref(ContentImage.png,left,nowrap,イメージのコンテンツ要素を格納)

***パネルに纏めて格納した複数のコンテンツ要素 [#a73fa28e]
-XAML
--2つ以上の要素を設定したい場合は、パネル要素を使用する。
 <Button Width="200" Height="200">
   <Button.Content>
     <StackPanel Orientation="Vertical">
       <Image Source=".\Blue hills.jpg" Margin="5" />
       <TextBlock Text="ボタン" HorizontalAlignment="Center" Margin="5"/>
     </StackPanel>
   </Button.Content>
 </Button>
--なお、<Object.Content>タグは省略することもできる。
 <Button Width="200" Height="200">
   <StackPanel Orientation="Vertical">
     <Image Source=".\Blue hills.jpg" Margin="5" />
     <TextBlock Text="ボタン" HorizontalAlignment="Center" Margin="5"/>
   </StackPanel>
 </Button>

-レンダリング結果
#ref(ContentStringAndImage.png,left,nowrap,パネルに纏めて格納した複数のコンテンツ要素)

**Itemsプロパティ [#v7960713]
WPFのItemsControlは、Itemsプロパティに任意の型の子要素を設定することができるため、コントロールの「外観」を自由に変更できる。

***複数のパネルに纏めて格納した複数のコンテンツ要素 [#w0ea6ec9]
ItemsControlのItemsプロパティへは、複数のコンテンツを追加できる。~
以下、ListBoxコントロールを例にしてItemsプロパティへ子要素の設定する例を示す。

-XAML
 <Grid>
   <ListBox>
     <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
       <StackPanel Orientation="Horizontal" Height="120" Width="250" Margin="5">
         <Image Source=".\Blue hills.jpg" Height="100"/>
         <TextBlock Text="Blue hills" VerticalAlignment="Center"/>
       </StackPanel>
     </Border>
     <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
       <StackPanel Orientation="Horizontal" Height="120" Width="250" Margin="5">
         <Image Source=".\Sunset.jpg" Height="100"/>
         <TextBlock Text="Sunset" VerticalAlignment="Center"/>
       </StackPanel>
     </Border>
     <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
       <StackPanel Orientation="Horizontal" Height="120" Width="250" Margin="5">
         <Image Source=".\Water lilies.jpg" Height="100"/>
         <TextBlock Text="Water lilies" VerticalAlignment="Center"/>
       </StackPanel>
     </Border>
     <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
       <StackPanel Orientation="Horizontal" Height="120" Width="250" Margin="5">
         <Image Source=".\Winter.jpg" Height="100"/>
         <TextBlock Text="Winter" VerticalAlignment="Center"/>
       </StackPanel>
     </Border>
   </ListBox>
 </Grid>
-レンダリング結果
#ref(ItemsControl.png,left,nowrap,複数のパネルに纏めて格納した複数のコンテンツ要素)

-説明
--Itemsプロパティに子要素を設定する場合は、~
innerText・innerXMLを使用する「[[プロパティ要素構文>#s389a559]]」を使用する。
---また、この際に<Object.Items>タグは省略することもできる。
--ちなみに、上記を「[[データ バインディング>#w4afa32c]]」で実装することもできる。
---これについては、「[[データ バインディングの基礎>#h0ae3316]]」を参照のこと。

*リソース [#p50dd8ac]
ここでは、

-「リソース」の定義方法と、

-前述の各「[[マークアップ拡張>#b565ab69]]」を使用し、~
プロパティ値に「リソース」への参照を指定する方法

について説明する。

※「リソース」の「[[データ バインディング>#w4afa32c]]」については、~
「[[リソースとのデータ バインディング>#eb81566f]]を参照のこと。

-参考
--MSDN > WPFの基礎 > リソース~
http://msdn.microsoft.com/ja-jp/library/ms742538.aspx

**リソースの定義 [#g7e2fd50]
「リソース」とは、ResourceDictionary 型のオブジェクトであり、
-ApplicationオブジェクトのResources プロパティ
-各UI要素(FrameworkElement or FrameworkContentElement)のResources プロパティ

に「[[プロパティ要素構文>#s389a559]]」を使用して定義できる。

-MSDN > .NET Frameworkクラス ライブラリ
-- > System.Windows.ResourceDictionaryクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.resourcedictionary.aspx
-- > System.Windows.Application.Resourcesプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.application.resources.aspx
-- > System.Windows.FrameworkElement.Resourcesプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.resources.aspx
-- > System.Windows.FrameworkContentElement.Resourcesプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkcontentelement.resources.aspx

このため、任意のUI要素に定義可能であるが、~
通常はルート要素(Window or Page)上に定義する。~

また、「リソース」は、定義場所により以下のような呼称・特徴がある。

***リソースの定義場所 [#qe6a5b64]

-アプリケーション リソース~
ApplicationオブジェクトのResourcesプロパティに定義された「リソース」を~
「アプリケーション リソース」と呼び、全体から(つまりどこからでも)参照できるという特徴を持っている。

-ウィンドウ ページ リソース~
Window・PageオブジェクトのResourcesプロパティに定義された「リソース」を~
「アプリケーション リソース」と呼び、そのWindow・Pageと、その子要素から参照できるという特徴を持っている。

-イミディエイト リソース~
各UI要素(FrameworkElement or FrameworkContentElement)の~
Resourcesプロパティに定義された「リソース」を「イミディエイト・リソース」と呼び、~
「リソース」を定義した要素と、その子要素から参照できるという特徴を持っている。

***リソースの定義例 [#sedc736a]
-「リソース」には、前述のx:Key ディレクティブを使用して一意のキーを持たせて定義する必要がある。~
 <Window.Resources>
   <x:Array x:Key="List" Type="{x:Type sys:String}">
     <sys:String>A</sys:String>
     <sys:String>B</sys:String>
     <sys:String>C</sys:String>
   </x:Array>
 </Window.Resources>
>※ 先頭で、String型のインポートが必要~
xmlns:sys="clr-namespace:System;assembly=mscorlib"

-補足:ジェネリック コレクションのリソース~
ジェネリック コレクションを「リソース」に定義するには、x:TypeArgumentsのディレクティブを使用して、~
ObservableCollection<T>コレクション クラスなどのジェネリック型のコンストラクタに渡す必要があるが、~
これは、XAML2009 からのサポートとなる。

***リソースの使用方法 [#r6badd32]
「リソース」を定義したら、各種「[[マークアップ拡張>#b565ab69]]」を使用して、~
プロパティ値に「[[データ バインディング>#w4afa32c]]」や、「リソース」への参照を指定できる。

この時、参照する側からx:Key ディレクティブを使用して割り当てたキーを「リソース」検索のキーとして指定できる。

なお、「[[スタイル>#v30d5ab6]]」や「[[テンプレート>#o64ea160]]」などは、キーを定義せず、TargetType 属性のみ使用して、~
指定の型のオブジェクトに「[[スタイル>#v30d5ab6]]」や「[[テンプレート>#o64ea160]]」を適用することもできる。~
これについては、「[[スタイルとテンプレート>#j0c577be]]」を参照のこと。

-MSDN > .NET Frameworkクラス ライブラリ
-- > System.Windows.Style.TargetType プロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.style.targettype.aspx
-- > System.Windows.Controls.ControlTemplate.TargetTypeプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.controltemplate.targettype.aspx

**リソースの定義と参照 [#wd960230]
以下、「リソース」の定義と、プロパティ値に「リソース」への参照を指定する例を示す。

***StaticResource参照の例 [#ybb9b94a]
StaticResource参照では、
-コンパイル時に「リソース」検索が行われ、各「リソース」に指定されたキーが存在するかどうかが確認される。
-「リソース」検索により、「リソース」が発見できなかった場合は、コンパイル時にエラーとなる。

以下は、StaticResourceの定義と参照例。

-XAML
--StaticResourceの定義と参照例(1)
---以下は、「[[マークアップ拡張>#b565ab69]]」を使用して、「[[プロパティ属性構文>#tb0bd2e6]]」でStaticResource参照した例である。
---また、属性名を省略すると自動的にコンストラクタに渡される動作を利用して、~
ResourceKey属性に指定の値を渡す旨を指示する「ResourceKey=」という記述を省略することができる。

>
 <Window.Resources>
   <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
 </Window.Resources>
 <Grid>
   <Ellipse Fill="{StaticResource ResourceKey=BlueBrush}" Height="150" Width="150"/>
 </Grid>

>↓ 「ResourceKey =」という記述を省略

>
 <Window.Resources>
   <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
 </Window.Resources>
 <Grid>
   <Ellipse Fill="{StaticResource BlueBrush}" Height="150" Width="150"/>
 </Grid>

--StaticResourceの定義と参照例(2)~
以下は、一般的ではないが「[[プロパティ要素構文>#s389a559]]」を使用してStaticResource参照した例である。~
なお、WPFのみ、StaticResource参照を「[[プロパティ要素構文>#s389a559]]」で記述可能である。
 <Window.Resources>
   <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
 </Window.Resources>
 <Grid>
   <Ellipse Height="150" Width="150">
     <Ellipse.Fill>
       <StaticResource ResourceKey="BlueBrush"/> 
     </Ellipse.Fill>
   </Ellipse>
 </Grid>

-レンダリング結果
#ref(StaticResource.png,left,nowrap,StaticResourceの定義と参照例(1))


***DynamicResource参照の例 [#h04a05da]
-DynamicResource参照では、アプリケーションの起動時に、~
後で「リソース」検索を行う際に使用する一時的な式が作成され、~
アプリケーションの実行後、「リソース」が必要になった際に都度、「リソース」検索が行われる。

-このためDynamicResource参照は、
--主に「リソース」の値が変更される場合、StaticResource参照に代替して使用する。
--「リソース」検索により、「リソース」が発見できなかった場合は、デフォルト値が設定される。

-なお、DynamicResource参照は、WPFでのみ利用可能で、「Silverlight」では利用不可である。

以下は、DynamicResourceの定義と参照例。

-以下は、リソースがアプリケーション外部から変更される場合の例~
以下は、デスクトップ画面のテーマの変更(Windows XP → Windowsクラシック)を反映する例である。~

>
 <Grid>
   <Grid.RowDefinitions>
     <RowDefinition/>
     <RowDefinition/>
   </Grid.RowDefinitions>
   <Ellipse Grid.Row="0"
     Fill="{StaticResource ResourceKey={x:Static SystemColors.HighlightBrushKey}}"/>
   <Ellipse Grid.Row="1"
     Fill="{DynamicResource ResourceKey={x:Static SystemColors.HighlightBrushKey}}"/>
 </Grid>

#ref(DynamicResource1.png,left,nowrap,DynamicResourceの定義と参照例(リソースがアプリケーション外部から変更される場合))

-以下は、リソースがアプリケーション内部から変更される場合の例~
以下は、アプリケーションからの「リソース」の動的な変更を反映する例である。~
なお、「リソース」の動的な変更は、FrameworkElement.Resourcesプロパティで変更できる。
--XAML
 <Window.Resources>
   <SolidColorBrush x:Key="MyBrush" Color="Blue"/>
 </Window.Resources>
 <Grid>
   <Grid.RowDefinitions>
     <RowDefinition/>
     <RowDefinition/>
     <RowDefinition Height="23"/>
   </Grid.RowDefinitions>
   <Ellipse Grid.Row="0" Fill="{StaticResource MyBrush}"/>
   <Ellipse Grid.Row="1" Fill="{DynamicResource MyBrush}"/>
   <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
     <Button Content="青" Height="23" Name="button1" Width="75" Click="button1_Click" />
     <Button Content="赤" Height="23" Name="button2" Width="75" Click="button2_Click" />
   </StackPanel>
 </Grid>

--コード ビハインド
 private void button1_Click(object sender, RoutedEventArgs e) {
   this.Resources["MyBrush"] = Brushes.Blue;
 }
 private void button2_Click(object sender, RoutedEventArgs e) {
   this.Resources["MyBrush"] = Brushes.Red;
 }

#ref(DynamicResource2.png,left,nowrap,DynamicResourceの定義と参照例(リソースがアプリケーション内部から変更される場合)

***StaticResource参照 + ディクショナリ ファイルの例 [#k8074527]
ResourceDictionaryは、「ディクショナリ ファイル」に定義することもできる。

「ディクショナリ ファイル」を追加する際は、
+プロジェクト ファイルを右クリックし、
+[追加] → [リソース ディクショナリ]を選択するか、~
[追加] → [新しい項目]を選択し、表示される[[テンプレート>#o64ea160]]から[リソース ディクショナリ(WPF)]を選択する。

#ref(AddDictionary.png,left,nowrap,ディクショナリ ファイルの追加)

-前述のStaticResource参照の例を、~
「ディクショナリ ファイル」を使用するように書き直した例を以下に示す。
 <ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
 </ResourceDictionary>
''ディクショナリ ファイルの定義例 (Dictionary1.xaml)''

-「ディクショナリ ファイル」を「イミディエイト・リソース」にロードする。
 <Window.Resources>
   <ResourceDictionary Source="Dictionary1.xaml"/>
 </Window.Resources>
 <Grid>
   <Ellipse Fill="{StaticResource BlueBrush}" Height="150" Width="150"/>
 </Grid>

>
#ref(StaticResourceAndDictionary.png,left,nowrap,StaticResource参照 + ディクショナリ ファイルの使用例)
''StaticResource参照 + ディクショナリ ファイルの使用例''

***DynamicResource参照 + ディクショナリ ファイルの例 [#z0de9556]
-DynamicResource参照とResourceDictionaryを組み合わせ、
-ResourceDictionaryを、Application.LoadComponentで動的にロード、
-Application.Current.Resourcesに設定することにより、
-「[[スタイル>#v30d5ab6]]」(スキン )などの設定をアプリケーションから動的に変更することが可能である。

以下の、その例を示す。

-Dictionary
--Dictionary1.xaml
 <ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <SolidColorBrush x:Key="MyBrush" Color="Blue"/>
 </ResourceDictionary>
--Dictionary2.xaml
 <ResourceDictionary
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <SolidColorBrush x:Key="MyBrush" Color="Red"/>
 </ResourceDictionary>

-XAML
 <StackPanel>
   <Ellipse Fill="{DynamicResource MyBrush}" Height="150" Width="150"/>
   <Button Content="青" Height="23" Name="button1" Width="75" Click="button1_Click" />
   <Button Content="赤" Height="23" Name="button2" Width="75" Click="button2_Click" />
 </StackPanel>

-コード ビハインド
 public partial class Window1 : Window {
   public Window1() {
     InitializeComponent();
     this.LoadResourceDictionary("Dictionary1.xaml");
   }
 
   private void button1_Click(object sender, RoutedEventArgs e) {
     this.LoadResourceDictionary("Dictionary1.xaml");
   }
 
   private void button2_Click(object sender, RoutedEventArgs e) {
     this.LoadResourceDictionary("Dictionary2.xaml");
   }
 
   private void LoadResourceDictionary(string name) {
     ResourceDictionary dictionary =
       (ResourceDictionary)Application.LoadComponent(new Uri(name, UriKind.Relative));
     if (dictionary != null) Application.Current.Resources = dictionary;
   }
 }

>
#ref(DynamicResourceAndDictionary.png,left,nowrap,DynamicResource参照 + ディクショナリ ファイルの使用例)

''DynamicResource参照 + ディクショナリ ファイルの使用例''

*データ バインディング [#w4afa32c]
様々なソースと「データ バインディング」するサンプルを示す。

なお、サンプルのXAMLソースを読むためには、以下の、~
Bindingプロパティの設定方法を理解しておく必要がある。

''Bindingプロパティの設定方法''
|項番|プロパティ|説明|h
|1|Mode|OneTime、OneWay、TwoWay のいずれかの「バインディング モード」を指定する。|
|2|Source|「バインディング ソース」を指定する。「バインディング ソース」は、&br;「[[リソース>#p50dd8ac]]」に定義し、[[StaticResourceの「マークアップ拡張」>#ybb9b94a]]を使用して「データ バインディング」するか、&br;FrameworkElement.DataContextから、「データ バインディング」する。|
|3|ElementName|UI要素名を使用して「バインディング ソース」を指定する。|
|4|[[RelativeSource>#b35e6e76]]|「バインディング ターゲット」からの相対位置で「バインディング ソース」を指定する。&br;※ Self、TemplatedParent、AncestorType、AncestorLevel属性などを使用して指定する。|
|5|Path|「バインディング ソース」のプロパティ名を指定する(名前空間のフルパスで指定可)。&br;なお、インデクサなどの指定も可能である。詳細は、以下のURLを参照のこと。|
|6|XPath|「バインディング ソース」として、XMLデータソースのXML DOMへのパスを表す文字列を指定する。|
|7|TargetNullValue|ソース値が null のときに返される値を指定する。|
|8|Converter|「[[値コンバータ>WPFのアーキテクチャ#nf7e2b6a]]」を指定する。&br;「[[値コンバータ>WPFのアーキテクチャ#nf7e2b6a]]」は、インスタンス化が可能であり、ResourceDictionaryに配置できる。&br;「[[値コンバータ>WPFのアーキテクチャ#nf7e2b6a]]」は「StaticResource」に定義し[[StaticResourceの「マークアップ拡張」>#ybb9b94a]]を使用して参照するようにする。|
|9|ConverterCulture|「[[値コンバータ>WPFのアーキテクチャ#nf7e2b6a]]」で使用するカルチャを指定する。|
|10|ConverterParameter|「[[値コンバータ>WPFのアーキテクチャ#nf7e2b6a]]」の変換ロジックで使用するパラメタを指定する。|

-MSDN > ・・・ > バインディングのマークアップ拡張機能~
http://msdn.microsoft.com/ja-jp/library/ms750413.aspx
--MSDN > ・・・ > PropertyPathのXAML構文~
http://msdn.microsoft.com/ja-jp/library/ms742451.aspx
--MSDN > ・・・ > 方法:XMLDataProviderとXPathクエリを試用してXMLデータにバインドする~
http://msdn.microsoft.com/ja-jp/library/ms749287.aspx

**データ バインディングの基礎 [#h0ae3316]
以下、「[[WPFのアーキテクチャ - データ バインディング>WPFのアーキテクチャ#dac6f2bf]]」に対応するサンプルを示す。

***コード ビハインドからのデータ バインディング(モード:OneWay) [#o2aaa11e]
-モード:OneWayの「データ バインディング」を行う。
-「データ バインディング」の基本的な動作を理解するために、
--Bindingオブジェクトをコード ビハインドで自作し、
--以下の2つのオブジェクトを結びつける。
---「バインディング ソース」
---「バインディング ターゲット」

-XAML
 <StackPanel 
   x:Name="MainPanel"
   Loaded="MainPanel_Loaded">
   <TextBlock x:Name="TextBlock1"/>
   <TextBlock x:Name="TextBlock2"/>
 </StackPanel>

-コード ビハインド
 public partial class Window1 : Window {
   public Window1() {
     InitializeComponent();
   }
 
   private void MainPanel_Loaded(object sender, RoutedEventArgs e)
   {
     // バインディング ソース(Person)
     Person BindingSource =
       new Person() { Height = 1.7, Weight = 60 };
 
     // Bindingオブジェクトによりバインド
 
     // HeightプロパティをOneWayでバインド
     Binding BindingHeight = new Binding("Height");
     BindingHeight.Mode = BindingMode.OneWay;
     // バインディング ソース(Person)
     BindingHeight.Source = BindingSource;
     // バインディング ターゲット(TextBlock)
     TextBlock1.SetBinding(TextBlock.TextProperty, BindingHeight);
 
     // WeightプロパティをOneWayでバインド
     Binding BindingWeight = new Binding("Weight");
     BindingWeight.Mode = BindingMode.OneWay;
     // バインディング ソース(Person)
     BindingWeight.Source = BindingSource;
     // バインディング ターゲット(TextBlock)
     TextBlock2.SetBinding(TextBlock.TextProperty, BindingWeight);
   } 
 }
 
 /// <summary>バインディング ソース(Person)</summary>
 public class Person {
   public double Height { get; set; }
   public double Weight { get; set; }
 }

***コード ビハインドからのDataContextを使用したデータ バインディング(モード:OneWay) [#mb48f656]

上記のMainPanel_Loadedメソッドのコードを一部編集し、MainPanel(StackPanel)の~
FrameworkElement.DataContextプロパティに「バインディング ソース」を設定することで、~
Bindingオブジェクトへの「バインディング ソース」の指定が不要になる。

-コード ビハインド
 private void MainPanel_Loaded(object sender, RoutedEventArgs e) {
   // バインディング ソース(Person)
   MainPanel.DataContext =
     new Person() { Height = 1.7, Weight = 60 };
 
   // Bindingオブジェクトによりバインド
 
   // HeightプロパティをOneWayでバインド
   Binding BindingHeight = new Binding("Height");
   BindingHeight.Mode = BindingMode.OneWay;
   // バインディング ターゲット(TextBlock)
   this.TextBlock1.SetBinding(TextBlock.TextProperty, BindingHeight);
 
   // WeightプロパティをOneWayでバインド
   Binding BindingWeight = new Binding("Weight");
   BindingWeight.Mode = BindingMode.OneWay;
   // バインディング ターゲット(TextBlock)
   TextBlock2.SetBinding(TextBlock.TextProperty, BindingWeight);
 }

***BindingオブジェクトをXAMLで実装する([[プロパティ要素構文>#s389a559]]) [#q82f9eb1]
-BindingオブジェクトをXAMLのマークアップ機能で実装する。~
更に、XAMLのマークアップ機能を使用して、Bindingオブジェクトの生成処理・設定処理をXAML側に移動することで、~
上記のXAMLとMainPanel_Loadedメソッドのコードを一部編集し、コード ビハインドのコード量を削減できる。

--XAML
 <StackPanel 
   x:Name="MainPanel"
   Loaded="MainPanel_Loaded">
   <TextBlock>
     <TextBlock.Text>
       <Binding Path="Height" Mode="OneWay"/>
     </TextBlock.Text>
   </TextBlock>
   <TextBlock>
     <TextBlock.Text>
       <Binding Path="Weight" Mode="OneWay"/>
     </TextBlock.Text>
   </TextBlock>
 </StackPanel>

--コード ビハインド
 private void MainPanel_Loaded
    (object sender, RoutedEventArgs e) {
 
   // バインディング ソース(Person)
   MainPanel.DataContext =
   new Person() { Height = 1.7, Weight = 60 };
 }

***Bindingオブジェクトをバインディングのマークアップ拡張で実装する([[プロパティ属性構文>#tb0bd2e6]]) [#ca5673d9]
-一般的には、「データ バインディング」を実装する場合、XAML側の記述は([[前述>#q82f9eb1]]とは異なる)~
「バインディングのマークアップ拡張」により「[[プロパティ属性構文>#tb0bd2e6]]」化して実装する方法を採る。

-上記のXAMLを「バインディングのマークアップ拡張」を使用して、「[[プロパティ属性構文>#tb0bd2e6]]」化して実装すると次のようになる。
 <StackPanel x:Name="MainPanel" Loaded="MainPanel_Loaded">
   <TextBlock Text="{Binding Path=Height, Mode=OneWay}" />
   <TextBlock Text="{Binding Path=Weight, Mode=OneWay}" />
 </StackPanel>

-また、属性名を省略すると自動的にコンストラクタに渡される動作を利用して、~
(Path属性に指定の値を渡す旨を指示する)「Path=」という記述を省略することができる。
 <StackPanel x:Name="MainPanel" Loaded="MainPanel_Loaded">
   <TextBlock Text="{Binding Height, Mode=OneWay}" />
   <TextBlock Text="{Binding Weight, Mode=OneWay}" />
 </StackPanel>

***変更通知の追加(モード:OneWay or OneWayToSource) [#iffee571]
下記は、モード:OneWay or OneWayToSourceを併用した「データ バインディング」によるBMI(肥満度)の自動計算アプリケーションの例である。~
この例では、「バインディング ソース」のプロパティ値の変更を、自動的に「バインディング ターゲット」に反映できる。~
なお、この際、「バインディング ソース」は、INotifyPropertyChangedインターフェイスを実装して、BMI(肥満度)プロパティの変更通知処理を実装する必要がある。

-XAML
 <StackPanel x:Name="MainPanel" Loaded="MainPanel_Loaded">
   <TextBox Margin="10" Text="{Binding Height, Mode=OneWayToSource}"/>
   <TextBox Margin="10" Text="{Binding Weight, Mode=OneWayToSource}"/>
   <Button Margin="10" Content="計算" Click="Button_Click" />
   <TextBlock Margin="10" Text="{Binding Bmi, Mode=OneWay}"/>
 </StackPanel>

-コード ビハインド
 /// <summary>/// Window1.xaml の相互作用ロジック/// </summary>
 public partial class Window1 : Window {
   public Window1() {
     InitializeComponent();
   }
 
   /// <summary>初期化イベント</summary>
   private void MainPanel_Loaded(object sender, RoutedEventArgs e) {
     // バインド ソース(Person)
     MainPanel.DataContext = new Person();
   }
   /// <summary>計算イベント</summary>
   private void Button_Click(object sender, RoutedEventArgs e) {
     ((Person)MainPanel.DataContext).Calculate();
   } 
 }

-バインディングソース
 /// <summary>バインド ソース(Person)</summary>
 public class Person : INotifyPropertyChanged {
   public double Height { get; set; }
   public double Weight { get; set; }
 
   double _bmi;
   public double Bmi {
     get { return this._bmi; }
     set {
       this._bmi = value;
 
       // 変更通知
       this.OnPropertyChanged("Bmi");
     }
   }
 
   /// <summary>計算処理</summary>
   public void Calculate() {
     this.Bmi = Weight / Math.Pow(Height, 2);
   }
 
   #region INotifyPropertyChanged メンバ
 
   /// <summary>値変更イベントの定義</summary>
   public event PropertyChangedEventHandler PropertyChanged;
 
   /// <summary>変更通知(値変更イベントを発生させる)</summary>
   protected virtual void OnPropertyChanged(string propertyName) {
     PropertyChangedEventHandler handler = this.PropertyChanged;
 
     if (handler != null)
       handler(this, new PropertyChangedEventArgs(propertyName));
   }
 
   #endregion
 }

***値コンバータを使用したデータ バインディング(モード:OneWay or OneWayToSource) [#jd1ebb3c]
続いて、上記処理に、BMI(肥満度)プロパティが
-18.5未満の場合、出力先のTextBlockの背景色を青色に
-25以上の場合、出力先のTextBlockの背景色を赤色に

変更する処理を追加する。

これには別途、背景色プロパティを定義することで実現することも可能であるが、~
ここでは、前述のIValueConverterインターフェイスを実装した「値コンバータ」を実装することでこれを実現する。~
値の変換処理は、「値コンバータ」のConvertメソッドに実装する。

-XAML
 <Window.Resources>
   <my:BmiLevelConverter x:Key="bmiLevelConverter"/>
 </Window.Resources>
 <StackPanel x:Name="MainPanel" Loaded="MainPanel_Loaded">
   <TextBox Margin="10" Text="{Binding Height, Mode=OneWayToSource}"/>
   <TextBox Margin="10" Text="{Binding Weight, Mode=OneWayToSource}"/>
   <Button Margin="10" Content="計算" Click="Button_Click" />
   <TextBlock Margin="10"
     Text="{Binding Bmi, Mode=OneWay}"
     Background="{Binding Bmi, Mode=OneWay,
     Converter={StaticResource bmiLevelConverter}}"/>
 </StackPanel>

-値コンバータ
 /// <summary>BMIレベルに合った背景色を返す</summary>
 public class BmiLevelConverter : IValueConverter {
   #region IValueConverter メンバ
 
   /// <summary>変換メソッド(ソースからターゲット)</summary>
   public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
     // BMIレベルに合った背景色を返す
     double target = (double)value;
     SolidColorBrush level;
 
     if (target < 18.5)
       level = new SolidColorBrush(Colors.Blue);
     else if (target > 25)
       level = new SolidColorBrush(Colors.Red);
     else
       level = new SolidColorBrush(Colors.White);
 
     return level;
   }
 
   /// <summary>変換メソッド(ターゲットからソース)</summary>
   public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
     throw new NotImplementedException();
   }
 
   #endregion
 }

***INotifyPropertyChangedの変更通知を「依存関係プロパティ」で代替 [#xdb6404a]
なお、変更通知は、INotifyPropertyChangedインターフェイスの実装ではなく、「依存関係プロパティ」でも代替できる。~
上記の例のBMI(肥満度)プロパティを「依存関係プロパティ」として、以下のように書き直し、動作を確認する。~

-バインディングソース
 /// <summary>バインド ソース(Person)</summary>
 public class Person : DependencyObject {
   public double Height { get; set; }
   public double Weight { get; set; }
 
   /// <summary>Bmiプロパティを依存関係プロパティとして登録</summary>
   public static readonly DependencyProperty BmiProperty =
     DependencyProperty.Register("Bmi", typeof(double), typeof(Person), 
         new UIPropertyMetadata(0.0));
 
   /// <summary>BmiプロパティのCLRプロパティ</summary>
   public double Bmi {
     get { return (double)this.GetValue(Person.BmiProperty); }
     set { this.SetValue(Person.BmiProperty, value); }
   }
 
   /// <summary>計算処理</summary>
   public void Calculate(){
     this.Bmi = Weight / Math.Pow(Height, 2);
   }
 }

BMI(肥満度)プロパティが変更されると、UI要素(TextBlock)に変更が反映されることを確認できる。~
このように、「依存関係プロパティ」は既定で変更通知をサポートしている。

***双方向のデータ バインディング(モード:TwoWay) [#q577d96c]
以下の例では、モード:TwoWayの「データ バインディング」を行うため、~
2つのUI要素、TextBoxとSliderを双方向接続した例である。

なお前述のようにUI要素の表示に関するプロパティは、~
基本的に「依存関係プロパティ」として定義されており、~
既定で変更通知をサポートしている。このため、既定で双方向接続が可能である。

なお、「バインディング ソース」をUI要素に接続する場合は、ElementName属性を使用すると良い。

-TextBox(ソース)→Slider(ターゲット)

--XAML
 <StackPanel Orientation="Vertical">
   <Label>TextBox</Label>
   <TextBox x:Name="textBox1" Text="5"/>
   <Rectangle Height="20"></Rectangle>
   <Label>Slider</Label>
   <Slider x:Name="Slider1" 
     Value="{Binding ElementName=textBox1, Path=Text, Mode=TwoWay}"/>
 </StackPanel>

-Slider(ソース)→TextBox(ターゲット)
--バインディング ソース、バインディング ターゲットを反転する。
--すると「バインディング ターゲット」(TextBox)の変更が直ちに通知されなくなる。~
(TextBoxから、フォーカスが外れないとSliderに変更値が反映されない)。
--これは、ほとんどの依存関係プロパティの既定値は PropertyChangedであるが、Textプロパティの既定値は LostFocusのため。
--この場合、「バインディングのマークアップ拡張」に、「UpdateSourceTrigger=PropertyChanged」 という属性の記述を追加することで、~
「バインディング ターゲット」(TextBox)からの変更が直ちに「バインディング ソース」(Slider)に通知されるようになる。

--XAML
 <StackPanel Orientation="Vertical">
   <Label>TextBox</Label>
   <TextBox x:Name="textBox1"
     Text="{Binding ElementName=Slider1, Path=Value, Mode=TwoWay}"/>
   <Rectangle Height="20"></Rectangle>
   <Label>Slider</Label>
   <Slider x:Name="Slider1" Value="5"/>
 </StackPanel>

--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Data.Binding
---UpdateSourceTriggerプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.data.binding.updatesourcetrigger.aspx
---UpdateSourceTrigger列挙体~
http://msdn.microsoft.com/ja-jp/library/system.windows.data.updatesourcetrigger.aspx

***値コンバータを使用したデータ バインディング(モード:TwoWay) [#gdc1bedf]
双方向の値の変換に対応した「値コンバータ」は、~
Convert、ConvertBackメソッドの双方を実装する必要がある。

-XAML
 <Window.Resources>
   <my:ValConverter x:Key="valConverter" />
 </Window.Resources>
 <StackPanel Orientation="Vertical">
   <Label>TextBox</Label>
   <TextBox x:Name="textBox1" Text="500"/>
   <Rectangle Height="20"></Rectangle>
   <Label>Slider</Label>
   <Slider x:Name="Slider1"
     Value="{Binding ElementName=textBox1, Path=Text, Mode=TwoWay,
     Converter={StaticResource valConverter}}"/>
 </StackPanel>

-コード ビハインド
 public class ValConverter : IValueConverter {
   #region IValueConverter メンバ
 
   /// <summary>変換メソッド(ソースからターゲット)</summary>
   public object Convert(object value, Type targetType,
     object parameter, System.Globalization.CultureInfo culture) {
     return int.Parse(value.ToString()) / 100;
   }
 
   /// <summary>変換メソッド(ターゲットからソース)</summary>
   public object ConvertBack(object value, Type targetType,
     object parameter, System.Globalization.CultureInfo culture) {
     return ((double)value) * 100;
   }
 
   #endregion
 }

***ItemsSourceへのデータ バインディング [#qe911f6c]
ItemsControlから派生した要素のItemsSource属性にコレクションを「データ バインディング」する場合、対象オブジェクトは反復処理をサポートしている必要がある。

-ItemsSourceへのデータ バインディング(UI要素を含まない「データ バインディング」)~
以下は、ObservableCollection<T> コレクション クラスを使用して「データ バインディング」する例である。~
なお、ObservableCollection<T>コレクション クラスは、INotifyPropertyChangedインターフェイスを継承しており、変更通知が可能となっている。

--XAML
 <StackPanel x:Name="stackPanel1">
   <ListBox x:Name="listBox1" ItemsSource="{Binding}"/>
   <Button Height="23" Name="button1" Click="button1_Click">Button</Button>
 </StackPanel>

--コード ビハインド
 public partial class Window1 : Window {
 
   ObservableCollection<string> _cities = new ObservableCollection<string>();
 
   public Window1() {
     InitializeComponent();
 
     this._cities.Add("札幌市");
     this._cities.Add("仙台市");
     this._cities.Add("静岡市");
 
     this.stackPanel1.DataContext = _cities;
   }
 
   private void button1_Click(object sender, RoutedEventArgs e) {
     this._cities.Add("神戸市" + this.listBox1.Items.Count.ToString());
   }
 }

--UI要素を含まない「データ バインディング」の実装例について、
---上記例では、button1_ClickイベントでItemがObservableCollection<T>コレクションに追加さると直ちにListBoxの表示に反映されることが確認できる。~
また、この変更通知をサポートしているObservableCollection<T>コレクション クラスを、変更通知をサポートしないCollection<T> コレクション クラスに変更した場合、~
Collection<T>コレクションに追加されたItemがListBoxの表示に反映されないことも確認できる。
---なお、変更通知に対応したカスタム コレクションを作成する場合は、~
ObservableCollection<T>や、Collection<T> & INotifyCollectionChangedを継承したカスタム コレクションを作成すると良い。
---この際の注意点としては、後者のCollection<T> & INotifyCollectionChangedを継承したカスタム コレクションを作成する場合、~
Add、RemoveAtなどのメソッドに変更通知を実装し、「変更通知の基盤処理」の値変更イベントに、~
前述のPropertyChangedEventHandlerではなく、NotifyCollectionChangedEventHandlerを使用する点である。

-ItemsSourceへのデータ バインディング(UI要素を含んだ「データ バインディング」)~
以下は、[[「Itemsプロパティ」>#v7960713]]の例を「データ バインディング」で実装した例である。

--XAML
 <StackPanel x:Name="stackPanel1">
   <ListBox ItemsSource="{Binding}"/>
 </StackPanel>

--コード ビハインド
 public Window1() {
   InitializeComponent();
 
   // バンディング ソース(コレクション)
   ObservableCollection<Border> cities = new ObservableCollection<Border>();
 
   // ワーク
   Border tmpBorder = null;
   StackPanel tmpStackPanel = null;
   Image tmpImage = null;
   TextBlock tmpTextBlock = null;
 
   // Borderの構築
   tmpBorder = new Border();
   tmpBorder.BorderBrush = Brushes.Black;
   tmpBorder.BorderThickness = new Thickness(1);
   tmpBorder.Margin = new Thickness(5);
 
   // StackPanelの構築
   tmpStackPanel = new StackPanel();
   tmpStackPanel.Orientation = Orientation.Horizontal;
   tmpStackPanel.Height = 120;
   tmpStackPanel.Width = 250;
   tmpStackPanel.Margin = new Thickness(5);
 
   // Imageの構築
   tmpImage = new Image();
   tmpImage.Source=new BitmapImage(
     new Uri(@".\Water lilies.jpg", UriKind.Relative));
   tmpImage.Height=100;
 
   // TextBlockの構築
   tmpTextBlock = new TextBlock();
   tmpTextBlock.Text="Water lilies";
   tmpTextBlock.VerticalAlignment = VerticalAlignment.Center;
 
   // 階層構造の組み立て
   tmpStackPanel.Children.Add(tmpImage);
   tmpStackPanel.Children.Add(tmpTextBlock);
 
   tmpBorder.Child = tmpStackPanel;
 
   // バンディング ソース(コレクション)に追加
   cities.Add(tmpBorder);
 
   // ・・・(n項繰り返し)・・・
 
   // データ バンディング
   stackPanel1.DataContext = cities;
 }

--UI要素を含んだ「データ バインディング」の実装例について、
---子要素を持つUI要素をコード ビハインドで作成し、これを「データ バインディング」する実装例も、一般的ではない。
---このような場合は、「[[テンプレート>#o64ea160]]」を使用するのが一般的である。
---「[[テンプレート>#o64ea160]]」を使用した実装例は、「[[スタイルとテンプレート>#j0c577be]]」 - 「[[テンプレート>#o64ea160]]」を参照のこと。

***インデクサによるデータ バインディング [#t27b49c9]
インデクサについても、Path属性に角括弧を指定することで接続可能である。

-XAML
 <Grid>
   <Image x:Name="Image1"
     Height="200" Width="200"
     Source="{Binding Path=[Source]}"
     ToolTip="{Binding Path=[ToolTip]}"/>
 </Grid>

-コード ビハインド
 public Window1() {
   InitializeComponent();
 
   Hashtable ht = new Hashtable();
   ht["Source"] = @".\Winter.jpg";
   ht["ToolTip"] = "Winter";
   this.Image1.DataContext = ht;
 }

これらを応用すると、~

インデクサを持つオブジェクトの配列(反復処理をサポート)~
をデータ バインディングすることも可能であることが分かる。

ビジネス・アプリケーションでは、DataGridへDataTableをデータ バインディングする際に、~
DataGridの列へDataTableの列をマッピングするようなケースでよく利用します。


**[[リソース>#p50dd8ac]]とのデータ バインディング [#eb81566f]
「[[リソース>#p50dd8ac]]」参照を「バインディングのマークアップ拡張」でも使用することができる。

***StaticResourceを使用したデータ バインディング [#q416a676]
-例えば、静的な「[[リソース>#p50dd8ac]]」を使用し、以下のように「データ バインディング」できる。

--StaticResourceのデータ バインディング (1)
 <Window.Resources>
   <sys:String x:Key="val">Click Here</sys:String >
 </Window.Resources>
 <StackPanel>
   <Button Content="{Binding Source={StaticResource val}}"/>
 </StackPanel>
>※ 先頭で、String型のインポートが必要~
xmlns:sys="clr-namespace:System;assembly=mscorlib"

-ItemsControlから派生したUIコントロールのItemsSource属性に「データ バインディング」する場合、~
「[[リソース>#p50dd8ac]]」の対象オブジェクトは反復処理をサポートしている必要がある。
--StaticResourceのデータ バインディング (2)
 <Window.Resources>
   <x:Array x:Key="list"
     Type="{x:Type sys:String}">
     <sys:String>A</sys:String>
     <sys:String>B</sys:String>
     <sys:String>C</sys:String>
   </x:Array>
 </Window.Resources>
 <StackPanel>
   <ListBox ItemsSource="{Binding Source={StaticResource list}}"/>
 </StackPanel>
>※ 先頭で、String型のインポートが必要~
xmlns:sys="clr-namespace:System;assembly=mscorlib"

***DynamicResourceを使用したデータ バインディング [#e00226e0]
動的な「[[リソース>#p50dd8ac]]」を使用した「データ バインディング」はサポートされない。~
以下、「{Binding Source={DynamicResource」をテストした際のエラーメッセージである。

 型 'Binding' の 'Source' プロパティで 'DynamicResourceExtension' を設定することはできません。'DynamicResourceExtension' は、DependencyObject の DependencyProperty でのみ設定できます。

-参考
--MSDN > .NET Frameworkクラス ライブラリ
--- > System.Windows.Data.Binding.Sourceプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.data.binding.source.aspx
--- > System.Windows.DynamicResourceExtensionクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.dynamicresourceextension.aspx

*レイアウト [#lc8aa2dd]
ココでは、レイアウト方法として、
-[[レイアウトのプロパティ>#ad27e006]]
-[[パネルの種類と使い方>#t2926641]]

の2つについて説明する。

-MSDN > WPFの基礎 > レイアウト システム~
http://msdn.microsoft.com/ja-jp/library/ms745058.aspx

**レイアウトのプロパティ [#ad27e006]
-ココでは、「レイアウト」関係のプロパティについて説明する。

-これらのプロパティは、「レイアウト」機能を追加するFrameworkElement基本クラスにより提供される。
--配置の際、各要素間に余白を指定したい場合は、Margin、Padding属性を使用する。
---Margin :自要素と親要素の間
---Padding:自要素と子要素の間~
※ [left, top, right, bottom]と設定可能。省略時の動作は、リファレンスを参照のこと。
--配置の際、「揃え」を指定したい場合は、HorizontalAlignment、VerticalAlignment属性を使用する。
---HorizontalAlignment :水平方法の揃え(Center、Left、Right、Stretchを指定可)
---VerticalAlignment   :垂直方法の揃え(Center、Top、Bottom、Stretchを指定可)~
※ Stretchは、引き伸ばして余白を埋めて配置の意味。

-以下、「レイアウト」関係のプロパティを使用したXAMLとレンダリングの例を示す。
--XAML
 <Border Background="LightBlue" BorderBrush="Black" BorderThickness="2" Padding="15">
   <StackPanel Background="White" HorizontalAlignment="Center" VerticalAlignment="Top">
     <TextBlock Margin="5,0,5,0" HorizontalAlignment="Center">Alignment, Margin and Padding Sample</TextBlock>
     <Button HorizontalAlignment="Left" Margin="20">Button 1</Button>
     <Button HorizontalAlignment="Right" Margin="10">Button 2</Button>
     <Button HorizontalAlignment="Stretch" Margin="0">Button 3</Button>
   </StackPanel>
 </Border>
--[[レンダリング>https://i-msdn.sec.s-msft.com/dynimg/IC155786.jpeg]]

-参考
--MSDN > WPFの基礎 > 基本要素 > 配置、余白、パディングの概要~
http://msdn.microsoft.com/ja-jp/library/ms751709.aspx

**パネルの種類と使い方 [#t2926641]
WPFでは、パネルを使用した「レイアウト」が可能である。

-パネルには、以下のような特徴がある。
--複数のUIElementを含めることができる(UIElementCollection のプロパティを持つ)。
---MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.UIElementCollectionクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.uielementcollection.aspx
>UIElement子要素の順序付けられたコレクションを表す。~
XAMLから「[[プロパティ要素構文>#s389a559]]」の「[[コンテンツ構文>#m4c088a5]]」でパネル要素に子要素を追加する場合は、~
&lt;Panel.Children&gt;タグを使用する(ただし、このタグを明示しなくとも、暗黙的に使用される)。~
また、コード ビハインドから、パネル要素に子要素を追加する場合は、Children.Add メソッドを使用する。

--自分に含まれるUIElementを管理する。
--パネル自体もUIElementであるため、パネルへの組み込みが可能

-使用可能なパネル要素には次のものがある。
|#|パネル名|クラス名|説明|h
|1|キャンバス パネル|Canvas|座標を使用して子要素を明示的に配置できる領域を定義する。|
|2|ドック パネル|DockPanel|パネルの各「辺」に、子要素をドッキングする領域を定義する。|
|3|スタック パネル|StackPanel|子要素を水平方向または垂直方向に整列する領域を定義する。|
|4|折り返しパネル|WrapPanel|子要素を水平方向または垂直方向に整列し、端に達したら改行して整列する領域を定義する。|
|5|(均一)グリッド パネル|UniformGrid|列と行で構成されているグリッド領域を定義する。|
|6|グリッド パネル|Grid|列と行で構成されている柔軟なグリッド領域を定義する。|

-また、親要素であるパネルへ配置する子要素の座標などの情報については、~
子要素から「添付プロパティ」を使用して設定可能である。

***キャンバス パネル [#p5a51a2b]
-座標を使用して子要素を明示的に配置できる領域を定義する。
--XAML
 <Canvas Background="LightSteelBlue">
   <TextBlock Canvas.Top="10" Canvas.Left="20">
     Hello World!
   </TextBlock>
   <TextBlock Canvas.Top="40" Canvas.Left="50">
     絶対位置決め方式は便利ではありませんか?
   </TextBlock>
 </Canvas>
--レンダリング結果
#ref(RenderingResultOfCanvas.png,left,nowrap,キャンバス パネル)


-キャンバス パネルでは、「添付プロパティ」であるCanvas.Top・Canvas.Left属性を使用して、~
子要素から座標位置を明示的に指定・配置できるため、Windowsフォームに近い開発が可能である。

-参考
--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.Canvasクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.canvas.aspx

***ドック パネル [#pe1b48eb]
-パネルの各「辺」に、子要素をドッキングする領域を定義する。
--XAML
 <DockPanel LastChildFill="True">
   <Border Height="25" Background="SkyBlue" DockPanel.Dock="Top">
     <TextBlock Foreground="Black">Dock = "Top(1)"</TextBlock>
   </Border>
   <Border Height="25" Background="SkyBlue" DockPanel.Dock="Top">
     <TextBlock Foreground="Black">Dock = "Top(2)"</TextBlock>
   </Border>
   <Border Height="25" Background="LemonChiffon" DockPanel.Dock="Bottom">
     <TextBlock Foreground="Black">Dock = "Bottom"</TextBlock>
   </Border>
   <Border Width="100" Background="PaleGreen" DockPanel.Dock="Left">
     <TextBlock Foreground="Black">Dock = "Left"</TextBlock>
   </Border>
   <Border Background="White">
     <TextBlock Foreground="Black">
       This content will "Fill" the remaining space
     </TextBlock>
   </Border>
 </DockPanel>
--レンダリング結果
#ref(RenderingResultOfDockPanel.png,left,nowrap,ドック パネル)

-DockPanel.LastChildFillプロパティ(LastChildFill属性)をtrue (既定値)に設定すると、~
DockPanelの最終の子要素は常に残りの領域を埋めるようになる。

-参考
--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.DockPanelクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.dockpanel.aspx

***スタック パネル [#i49c2e00]
-子要素を水平方向または垂直方向に整列する領域を定義する。
--XAML
---水平方向
 <StackPanel Orientation="Horizontal">
   <RadioButton Margin="4">test1</RadioButton>
   <RadioButton Margin="4">test2</RadioButton>
   <RadioButton Margin="4">test3</RadioButton>
 </StackPanel>
---垂直方向
 <StackPanel Orientation="Vertical">
   <RadioButton Margin="4">test1</RadioButton>
   <RadioButton Margin="4">test2</RadioButton>
   <RadioButton Margin="4">test3</RadioButton>
 </StackPanel>
--レンダリング結果
---水平方向
#ref(HorizontalRenderingResultOfStackPanel.png,left,nowrap,水平のスタック パネル)
---垂直方向
#ref(VerticalRenderingResultOfStackPanel.png,left,nowrap,垂直のスタック パネル)

-整列方向は、StackPanel.Orientationプロパティ(Orientation属性)で指定する。

-参考
--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.StackPanelクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.stackpanel.aspx

***折り返しパネル [#c1367ccd]
-子要素を水平方向または垂直方向に整列し、端に達したら改行して整列する領域を定義する。~
※ パネルのサイズが変更されると、改行位置も変更される。
--XAML
---水平方向
 <WrapPanel Orientation="Horizontal">            
   <Button Width="26" Height="26" Margin="4" Content="0"></Button>
   <Button Width="26" Height="26" Margin="4" Content="1"></Button>
   <Button Width="26" Height="26" Margin="4" Content="2"></Button>
  ・・・
   <Button Width="26" Height="26" Margin="4" Content="7"></Button>
   <Button Width="26" Height="26" Margin="4" Content="8"></Button>
   <Button Width="26" Height="26" Margin="4" Content="9"></Button>
 </WrapPanel>
---垂直方向
 <WrapPanel Orientation="Vertical">            
   <Button Width="26" Height="26" Margin="4" Content="0"></Button>
   <Button Width="26" Height="26" Margin="4" Content="1"></Button>
   <Button Width="26" Height="26" Margin="4" Content="2"></Button>
  ・・・
   <Button Width="26" Height="26" Margin="4" Content="7"></Button>
   <Button Width="26" Height="26" Margin="4" Content="8"></Button>
   <Button Width="26" Height="26" Margin="4" Content="9"></Button>
 </WrapPanel>
--レンダリング結果
---水平方向
#ref(HorizontalRenderingResultOfWrapPanel.png,left,nowrap,水平の折り返しパネル)
---垂直方向
#ref(VerticalRenderingResultOfWrapPanel.png,left,nowrap,垂直の折り返しパネル)

-整列方向は、WrapPanel.Orientationプロパティ(Orientation属性)で指定する。

-参考
--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.WrapPanelクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.wrappanel.aspx

***(均一)グリッド パネル [#h66a8f8e]
-列と行で構成されているグリッド領域を定義する。~
※ グリッド内のすべてのセルが同じサイズである必要がある。
--XAML
---3行 * 4列
 <UniformGrid Rows="3" Columns="4"> 
   <Button Width="26" Height="26" Margin="4" Content="0"></Button>
   <Button Width="26" Height="26" Margin="4" Content="1"></Button>
   <Button Width="26" Height="26" Margin="4" Content="2"></Button>
  ・・・
   <Button Width="26" Height="26" Margin="4" Content="7"></Button>
   <Button Width="26" Height="26" Margin="4" Content="8"></Button>
   <Button Width="26" Height="26" Margin="4" Content="9"></Button>
 </UniformGrid>
---4行 * 3列
 <UniformGrid Rows="4" Columns="3">
   <Button Width="26" Height="26" Margin="4" Content="0"></Button>
   <Button Width="26" Height="26" Margin="4" Content="1"></Button>
   <Button Width="26" Height="26" Margin="4" Content="2"></Button>
  ・・・
   <Button Width="26" Height="26" Margin="4" Content="7"></Button>
   <Button Width="26" Height="26" Margin="4" Content="8"></Button>
   <Button Width="26" Height="26" Margin="4" Content="9"></Button>
 </UniformGrid>
--レンダリング結果
---3行 * 4列
#ref(RenderingResultOfUniformGrid34.png,left,nowrap,3行 * 4列の(均一)グリッド パネル)
---4行 * 3列
#ref(RenderingResultOfUniformGrid43.png,left,nowrap,4行 * 3列の(均一)グリッド パネル)

-行・列数は、UniformGrid.Rows、UniformGrid.Columns属性(UniformGrid. Rows・Columnsプロパティ)で指定する。

-参考
--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.UniformGridクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.primitives.uniformgrid.aspx

***グリッド パネル [#p94f8aa7]
-列と行で構成されている柔軟なグリッド領域を定義する。
--行・列の定義にGrid.RowDefinitions、Grid.ColumnDefinitionsタグを使用する。
---「添付プロパティ」であるGrid.Row・Grid.Column属性を使用して子要素をセルへ配置する。
---列長・行長の設定も、この属性で指定する。
---このためHTMLのテーブルと使い方は異なる。

--XAML ( 4行 * 3列
 <Grid Width="250" Height="100">
   <Grid.ColumnDefinitions>
     <ColumnDefinition />
     <ColumnDefinition />
     <ColumnDefinition />
   </Grid.ColumnDefinitions>
   <Grid.RowDefinitions>
     <RowDefinition />
     <RowDefinition />
     <RowDefinition />
     <RowDefinition />
   </Grid.RowDefinitions>
 
   <TextBlock Grid.ColumnSpan="3" Grid.Row="0">2005 Products Shipped</TextBlock>
   <TextBlock Grid.Row="1" Grid.Column="0">Quarter 1</TextBlock>
   <TextBlock Grid.Row="1" Grid.Column="1">Quarter 2</TextBlock>
   <TextBlock Grid.Row="1" Grid.Column="2">Quarter 3</TextBlock>
   <TextBlock Grid.Row="2" Grid.Column="0">50000</TextBlock>
   <TextBlock Grid.Row="2" Grid.Column="1">100000</TextBlock>
   <TextBlock Grid.Row="2" Grid.Column="2">150000</TextBlock>
   <TextBlock Grid.ColumnSpan="3" Grid.Row="3">Total Units: 300000</TextBlock>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfGrid43.png,left,nowrap,4行 * 3列のグリッド パネル)

-なお、ColumnDefinitionタグのWidth属性に" n*"と指定することで、比率を指定できる。
--XAML ( 比率を指定
 <Grid>
   <Grid.ColumnDefinitions>
     <ColumnDefinition Width="1*"></ColumnDefinition>
     <ColumnDefinition Width="2*"></ColumnDefinition>
     <ColumnDefinition Width="3*"></ColumnDefinition>
   </Grid.ColumnDefinitions>
   <Grid.RowDefinitions>
     <RowDefinition Height="1*"></RowDefinition>
     <RowDefinition Height="2*"></RowDefinition>
     <RowDefinition Height="3*"></RowDefinition>
   </Grid.RowDefinitions>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfGridRatio.png,left,nowrap,比率指定したグリッド パネル)

-参考
--MSDN > .NET Frameworkクラス ライブラリ > System.Windows.Controls.Gridクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.grid.aspx

*スタイルとテンプレート [#j0c577be]
ココでは、「外観」に関する設定を行う「[[スタイル>#v30d5ab6]]」と「[[テンプレート>#o64ea160]]」について説明する。

-参考
--MSDN > WPFの基礎 > スタイルとテンプレート : 概念~
http://msdn.microsoft.com/ja-jp/library/bb613570.aspx
---> スタイルとテンプレート~
http://msdn.microsoft.com/ja-jp/library/ms745683.aspx
---> ControlTemplateの作成による既存のコントロールの外観のカスタマイズ~
http://msdn.microsoft.com/ja-jp/library/ee230084.aspx

--MSDN > Windows Presentation Foundation > コントロール
---> コントロールのカスタマイズ > ControlTemplateの例~
http://msdn.microsoft.com/ja-jp/library/aa970773.aspx

**スタイル [#v30d5ab6]
[[WPF]] / [[Silverlight]]で外観をカスタマイズする仕組みのこと。

***スタイルの基本 [#x9dade50]
「スタイル」は、UI要素の「依存関係プロパティ」の一括管理機能を持ち、これを使用して「外観」に統一性を持たせるための機能である。~
「スタイル」は、Style型のオブジェクトであり、各UI要素(FrameworkElement or FrameworkContentElement)のStyleプロパティに指定可能である。

-外観に関する値を設定する「[[プロパティ属性構文>#tb0bd2e6]]」~
以下は、UI要素の「依存関係プロパティ」に、「外観」に関するFill、Height、Width属性の属性値を設定する「[[プロパティ属性構文>#tb0bd2e6]]」である。
--XAML
 <Grid>
   <Ellipse Fill="Blue" Height="80" Width="160"/>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfStyle1.png,left,nowrap,外観に関する値を設定する「プロパティ属性構文」)

-[[プロパティ属性構文>#tb0bd2e6]]のスタイル化
--上記を、「[[プロパティ要素構文>#s389a559]]」を使用してStyle型のオブジェクトを生成し、Styleプロパティにこれを指定する例を以下に示す。
---TargetType属性により、「スタイル」は指定の型(ここではEllipse要素)に適用される。
---このTargetType属性による型指定が無いと、対象のプロパティの有・無などが判別できないため、型指定は必須となっている。

--XAML
 <Grid>
   <Ellipse>
     <Ellipse.Style>
       <Style TargetType="Ellipse">
         <Setter Property="Fill" Value="Blue"/>
         <Setter Property="Height" Value="80"/>
         <Setter Property="Width" Value="160"/>
       </Style>
     </Ellipse.Style>
   </Ellipse>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfStyle2.png,left,nowrap,プロパティ属性構文のスタイル化)

-スタイルを[[リソース>#p50dd8ac]]として定義
--なお、上記の「スタイル」化は、通常のプロパティ設定を冗長に記述しているに過ぎず、何の意味もなさない。
--このため、通常、「スタイル」を「[[リソース>#p50dd8ac]]」として定義し、各UI要素のStyleプロパティにはStaticResource参照を使用して設定する。

--以下は、x:Keyを明示した例である。
---XAML
   <StackPanel.Resources>
     <Style x:Key="EllipseStyle" TargetType="Ellipse">
       <Setter Property="Fill" Value="Blue"/>
       <Setter Property="Height" Value="80"/>
       <Setter Property="Width" Value="160"/>
     </Style>
   </StackPanel.Resources>
   <Ellipse Style="{StaticResource EllipseStyle}"/>
   <Ellipse Style="{StaticResource EllipseStyle}"/>
 </StackPanel>
---レンダリング結果
#ref(RenderingResultOfStyle3.png,left,nowrap,スタイルをリソースとして定義)

-ベースクラスの型にスタイルを適用~
また、派生元(ここではShape型)が同じであれば、異なる要素でも同じ「スタイル」を適用できる。
--XAML
 <StackPanel>
   <StackPanel.Resources>
     <Style x:Key="ShapeStyle" TargetType="Shape">
       <Setter Property="Fill" Value="Blue"/>
       <Setter Property="Height" Value="80"/>
       <Setter Property="Width" Value="160"/>
     </Style>
   </StackPanel.Resources>
   <Ellipse Style="{StaticResource ShapeStyle}"/>
   <Rectangle Style="{StaticResource ShapeStyle}"/>
 </StackPanel>
--レンダリング結果
#ref(RenderingResultOfStyle4.png,left,nowrap,ベースクラスの型にスタイルを適用)

-スタイルを全体に適用する例~
x:Keyを設定しなければ、TargetType属性により、「スタイル」は指定の型(ここではEllipse型)、全体に適用される~
(ただし、派生元が同じだが、型の異なる全ての要素に「スタイル」を適用することはできない)。~
--XAML
 <StackPanel>
   <StackPanel.Resources>
     <Style TargetType="Ellipse">
       <Setter Property="Fill" Value="Blue"/>
       <Setter Property="Height" Value="80"/>
       <Setter Property="Width" Value="160"/>
     </Style>
   </StackPanel.Resources>
   <Ellipse/>
   <Ellipse/>
 </StackPanel>
--レンダリング結果
#ref(RenderingResultOfStyle5.png,left,nowrap,スタイルを全体に適用する例)

***スタイルの継承 [#g2818cb4]
-TargetType プロパティが同じ2つのStyleクラスを定義し、~
BasedOnプロパティに継承元となるStyleクラスを設定することで、
>「スタイル」の継承が可能である。

>(Silverlight 2のStyleクラスにはBasedOnプロパティが存在しなかったが、Silverlight 3で追加されている)

-スタイルの継承例
--XAML
 <StackPanel>
   <StackPanel.Resources>
     <Style x:Key="EllipseBaseStyle" TargetType="Ellipse">
       <Setter Property="Fill" Value="Blue"/>
       <Setter Property="Height" Value="80"/>
       <Setter Property="Width" Value="160"/>
     </Style>
     <Style x:Key="EllipseInheritedStyle" TargetType="Ellipse"
       BasedOn="{StaticResource EllipseBaseStyle}">
       <Setter Property="Stroke" Value="Yellow"/>
       <Setter Property="StrokeThickness" Value="10"/>
     </Style>
   </StackPanel.Resources>
   <Ellipse Style="{StaticResource EllipseBaseStyle}"/>
   <Ellipse Style="{StaticResource EllipseInheritedStyle}"/>
  </StackPanel>
--レンダリング結果
#ref(RenderingResultOfInheritedStyle.png,left,nowrap,スタイルの継承例)

***外部ディクショナリ ファイル化 [#je240854]
-「ディクショナリ ファイル」を使用して、CSSファイルのように、~
「スタイル」を外部ディクショナリ ファイルに定義することも可能である。

-以下は、「ディクショナリ ファイル」を使用する例である。
--XAML
 <Window.Resources>
   <ResourceDictionary Source="Dictionary1.xaml"/>
 </Window.Resources>
 <StackPanel>
   <StackPanel.Resources>
     <Style x:Key="EllipseInheritedStyle" TargetType="Ellipse"
       BasedOn="{StaticResource EllipseBaseStyle}">
       <Setter Property="Stroke" Value="Yellow"/>
       <Setter Property="StrokeThickness" Value="10"/>
     </Style>
   </StackPanel.Resources>
   <Ellipse Style="{StaticResource EllipseBaseStyle}"/>
   <Ellipse Style="{StaticResource EllipseInheritedStyle}"/>
 </StackPanel>
--XAML ( 外部ディクショナリ ファイル : Dictionary1.xaml
 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Style x:Key="EllipseBaseStyle" TargetType="Ellipse">
     <Setter Property="Fill" Value="Blue"/>
     <Setter Property="Height" Value="80"/>
     <Setter Property="Width" Value="160"/>
   </Style>
 </ResourceDictionary>

***実行時スタイル [#aef5f69e]
-「[[リソースの定義と参照>#wd960230]]」の
--DynamicResource参照
--ディクショナリ ファイル

>の方法を、「スタイル」でも応用可能である。

-上記の例のXAMLを以下のように書き換え、~
コード ビハインドからResourceDictionaryを切り換え~
「スタイル」(スキン)を実行時に、動的に切り換えることができる。
--XAML
 <StackPanel>
   <Ellipse Style="{DynamicResource MyEllipseStyle}"/>
   <Button Content="青" Height="23" Name="button1" Width="75" Click="button1_Click" />
   <Button Content="赤" Height="23" Name="button2" Width="75" Click="button2_Click" />
 </StackPanel>
--XAML ( 外部ディクショナリ ファイル :
---Dictionary1.xaml
 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <Style x:Key="MyEllipseStyle" TargetType="Ellipse">
     <Setter Property="Fill" Value="Blue"/>
     <Setter Property="Height" Value="80"/>
     <Setter Property="Width" Value="160"/>
   </Style>
 </ResourceDictionary>
---Dictionary2.xaml
 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     <Style x:Key="MyEllipseStyle" TargetType="Ellipse">
         <Setter Property="Fill" Value="Red"/>
         <Setter Property="Height" Value="160"/>
         <Setter Property="Width" Value="80"/>
     </Style>
 </ResourceDictionary>
--コード・ビハインド
 public partial class Window1 : Window {
   public Window1() {
     InitializeComponent();
     this.LoadResourceDictionary("Dictionary1.xaml");
   }
 
   private void button1_Click(object sender, RoutedEventArgs e) {
     this.LoadResourceDictionary("Dictionary1.xaml");
   }
 
   private void button2_Click(object sender, RoutedEventArgs e) {
     this.LoadResourceDictionary("Dictionary2.xaml");
   }
 
   private void LoadResourceDictionary(string name) {
     ResourceDictionary dictionary =
       (ResourceDictionary)Application.LoadComponent(new Uri(name, UriKind.Relative));
     if (dictionary != null) Application.Current.Resources = dictionary;
   }
 }
--レンダリング結果
#ref(RenderingResultOfStyleAtRuntime.png,left,nowrap,実行時スタイル)

**テンプレート [#o64ea160]
[[WPF]] / [[Silverlight]]で外観をカスタマイズする仕組みのこと。

***テンプレートの基本 [#l20b9ab9]
-「[[コンテンツ構文>#m4c088a5]]」でも述べたように、WPFのUIコントロールは、~
「[[プロパティ属性構文>#tb0bd2e6]]」と「[[プロパティ要素構文>#s389a559]]」を使用することによって、
--「[[スタイル>#v30d5ab6]]」属性の指定だけでなく、
--[[Contentプロパティ>#gc84bde8]](または[[Itemsプロパティ>#v7960713]])に
--「[[スタイル>#v30d5ab6]]」属性の設定だけでなく、
--[[Contentプロパティ>#gc84bde8]](または[[Itemsプロパティ>#v7960713]])に任意の型の子要素を設定することができる。

>任意の型の子要素を設定することができる。
>このため、WPFのUIコントロールはコントロールの「外観」を自由に変更でき、柔軟性が非常に高くなっている。

-このため、WPFのUIコントロールはコントロールの「外観」を自由に変更でき、柔軟性が非常に高くなっている。
|#|コントロールのクラス型|コンテンツを設定するプロパティ|説明|h
|1|ContentControlクラス|[[Contentプロパティ>#gc84bde8]]|ContentControl.Contentプロパティにコントロールの外観を設定できる。|
|2|ItemsControlクラス|[[Itemsプロパティ>#v7960713]]|ItemsControl.Itemsプロパティにコントロールの外観を設定できる。|

-また、「テンプレート」により、
--コントロールの「外観」を宣言型マークアップでカスタマイズ可能になる(「テンプレート」を複数の子要素から構成する)。
--コントロールの「外観」を宣言型マークアップでカスタマイズ可能になる。
--また、「イベント ハンドラ」や「イベント トリガ」なども、この「テンプレート」により定義可能で、~
「テンプレート」を「[[スタイル>#v30d5ab6]]」化することで、任意の型のコントロールに、これらの「テンプレート」の定義の適用を強制できる。
「テンプレート」を「[[スタイル>#v30d5ab6]]」化、「[[リソース>#p50dd8ac]]」化することで、任意の型のコントロールに、これらの「テンプレート」の定義の適用を強制できる。

-「テンプレート」は、コントロールの用途毎に、複数のものが用意されている。
--テンプレートを設定するのプロパティと、テンプレートの型
|#|テンプレートを設定するプロパティ|テンプレートのクラス型|説明|h
|1|Control.Template|ControlTemplate|Control.Templateプロパティに設定するControlTemplateクラスは、&br;Controlコントロールを表示する「テンプレート」を定義する際に使用する。|
|2|ContentControl.ContentTemplate|DataTemplate|ContentControl.ContentTemplateプロパティに設定するDataTemplateクラスは、&br;ContentControlコントロールの[[Contentプロパティ>#gc84bde8]]のデータを表示する「テンプレート」を定義する際に使用する。|
|3|ItemsControl.ItemTemplate|DataTemplate|ItemsControl.ItemTemplateプロパティに設定するDataTemplateクラスは、&br;ItemsControlコントロールの[[Itemsプロパティ>#v7960713]]のデータを使用する「テンプレート」を定義する際に使用する。|
|4|HeaderTemplate、CellTemplateなど|DataTemplate|種々のコントロールに独自のテンプレートが存在する。|
|#|>|テンプレートを設定するプロパティ|テンプレートのクラス型|>|説明|h
|1|>|[[Control.Template>http://msdn.microsoft.com/ja-jp/library/system.windows.controls.control.template.aspx]]|[[ControlTemplate>http://msdn.microsoft.com/ja-jp/library/system.windows.controls.controltemplate.aspx]]|>|Controlコントロールの全体の外観をカスタマイズする「テンプレート」を定義する際に使用する。&br;各種プロパティを表示する場合、各種プロパティを表示するための要素をControlTemplateクラスに含める。|
|1-1||ContentControlの(Control. )Templateプロパティ|~||Contentプロパティを表示する場合、ContentControl.Contentプロパティを表示するContentPresenterクラスをControlTemplateクラスに含める。|
|1-2||ItemsControlの(Control. )Templateプロパティ|~||Itemsプロパティを表示する場合、ItemsControl.Itemsプロパティを表示するItemsPresenterクラスをControlTemplateクラスに含める。|
|2|>|XXXX.XXXXTemplate|[[DataTemplate>http://msdn.microsoft.com/ja-jp/library/system.windows.datatemplate.aspx]]|>|ContentControlやItemsControlコントロールのデータの外観をカスタマイズする「テンプレート」を定義する際に使用する。&br;各種データを表示する場合、各種データを表示するための要素をDataTemplateクラスに含める。|
|2-1||[[ContentControl.ContentTemplate>http://msdn.microsoft.com/ja-jp/library/system.windows.controls.contentcontrol.contenttemplate.aspx]]|~||ContentControl.ContentTemplateプロパティには、各種データを表示するための要素を含めたDataTemplateクラスを設定する。|
|2-2||[[ItemsControl.ItemTemplate>http://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemscontrol.itemtemplate.aspx]]|~||ItemsControl.ItemTemplateプロパティには、各種データを表示するための要素を含めたDataTemplateクラスを設定する。|
|3|>|その他|-|>|種々のコントロールの個別領域の外観をカスタマイズする「テンプレート」を設定する際に使用する。|
|3-1||[[ItemsControl.ItemsPanel>https://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemscontrol.itemspanel.aspx]]|[[ItemsPanelTemplate>https://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemspaneltemplate.aspx]]||Itemsプロパティに設定したコレクションの並びをカスタマイズできる。|
|3-2||[[HeaderedContentControl.HeaderTemplate>https://msdn.microsoft.com/ja-jp/library/system.windows.controls.headeredcontentcontrol.headertemplate.aspx]]|[[DataTemplate>http://msdn.microsoft.com/ja-jp/library/system.windows.datatemplate.aspx]]||ヘッダ・データの表示をカスタマイズできる。|
|3-3||[[GridViewColumn.CellTemplate>https://msdn.microsoft.com/ja-jp/library/system.windows.controls.gridviewcolumn.celltemplate.aspx]]|~||セル・データの表示をカスタマイズできる。|

-ただし、「テンプレート」で作成できる「外観」は、静的なものに限られる。

-参考
--MSDN > Windows Presentation Foundation
---> データ > データ バインディング > データ テンプレートの概要~
http://msdn.microsoft.com/ja-jp/library/ms742521.aspx
--MSDN > .NET Frameworkクラス ライブラリ
---> System.Windows.Controls.Control.Templateプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.control.template.aspx
---> System.Windows.Controls.ContentControl.ContentTemplateプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.contentcontrol.contenttemplate.aspx
---> System.Windows.Controls.ItemsControl.ItemTemplateプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemscontrol.itemtemplate.aspx
---> System.Windows.Controls.ControlTemplateクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.controltemplate.aspx
---> System.Windows.DataTemplateクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.datatemplate.aspx
***ControlTemplateとDataTemplate [#n86551dd]
-ControlTemplate
--Control自身の見た目を決定するもの。
--多くの場合TemplateBindingを使い、テンプレート親とのコントロールとしてのデータとのバインドを作成する。

-DataTemplate
--Controlに割り当てられたデータの見た目を定義するもの。
--多くの場合Bindingを使い、割り当てられたデータとのバインドを作成する。

-ControlTemplateとDataTemplateの使い分け

--その1
---ControlTemplate~
カスタマイズしたいものがコントロール自身である場合にを利用する。
---DataTemplate~
カスタマイズしたいものが割り当てられるデータである場合にを利用する。

--その2~
状況によっては、ControlTemplate、DataTemplateの~
どちらを使っても可能なこともあるので、再利用性で考える。
---ControlTemplate~
そのカスタマイズした結果できるであろうコントロールに、別のデータを載せることがある場合。
---DataTemplate~
そのカスタマイズした結果できるであろうコントロールに、別のデータを載せることがない場合。

--その3
---ControlTemplate~
ContentControlをカスタマイズする場合。
---DataTemplate~
ItemsControlをカスタマイズする場合。

***「テンプレート」値を反映させる方法 [#wc88b865]
また、親コントロールに適用した、「テンプレート」の値を~
[[Contentプロパティ>#gc84bde8]](または[[Itemsプロパティ>#v7960713]])を含む~
プロパティ値に反映させるにめには、下記の3通りの方法を使用できる。
プロパティ値に反映させるにめには、下記の3通りの方法を選択的に使用できる。

-「プレゼンター」を利用する方法
--親コントロールの[[Contentプロパティ>#gc84bde8]]の場合は、ContentPresenter を用いる。~
[[Contentプロパティ>#gc84bde8]]は、任意の型の子要素を取得し、「テンプレート」に反映できる。

--また、ItemsControlの[[Itemsプロパティ>#v7960713]]に対応するものにItemsPresenter があり、~
[[Itemsプロパティ>#v7960713]]の並びを、ItemsControlのItemsPanel プロパティのItemsPanelTemplate で変更できる。
[[Itemsプロパティ>#v7960713]]は、任意の型の子要素を取得し、「テンプレート」に反映できる。

--その他、コントロールによって、ScrollContentPresenter 、CellValuePresenterなどの「プレゼンター」が用意されている。
--その他、コントロールによって、色々なテンプレート・プレゼンターが用意されている。
---テンプレート : ItemsControl.ItemsPanelプロパティのItemsPanelTemplate.
>参考 : FrameworkTemplate クラス (System.Windows)~
https://msdn.microsoft.com/ja-jp/library/system.windows.frameworktemplate(v=vs.110).aspx

--なお、DataTemplateは、
---ContentPresenter([[Contentプロパティ>#gc84bde8]])
---ItemsPresenter([[Itemsプロパティ>#v7960713]])~
の表示をカスタマイズするための「テンプレート」である。~
このため、ControlTemplateとDataTemplateの両方のカスタマイズを行う場合は、~
ControlTemplate側に必ず、ContentPresenter・ItemsPresenterを含める必要がある点に注意が必要である。
---プレゼンター : ScrollContentPresenter, CellValuePresenter、etc.
>参考 : 【WPF】Presenter(?)クラスを収集と考察。 | 創造的プログラミングと粘土細工~
http://pro.art55.jp/?eid=931821

-[[TemplateBinding の「マークアップ拡張」>#hee73def]]を使用する。~
親コントロールに適用したプロパティ値を「テンプレート」に反映させる。
 <object property="{TemplateBinding TargetProperty }" .../>

-同様に、[[RelativeSource の「マークアップ拡張」>#b35e6e76]]も使用できる。
 <Binding RelativeSource="{RelativeSource TemplatedParent}" .../>
--なお、「データ バインディング」で使用する場合は、次のようになる。
 <object property="{Binding RelativeSource={RelativeSource TemplatedParent} ...}" .../>
--RelativeSourceの例
---XAML
 <StackPanel>
 
   <TextBlock Text="{Binding RelativeSource
     ={RelativeSource Self}, Path=FontFamily}" />・・・(1)
 
   <Border Background="Black" Height="5"/>
 
   <TextBlock Text="{Binding RelativeSource
     ={RelativeSource AncestorType={x:Type StackPanel}},Path=Orientation}" />・・・(2)
 
   <Border Background="Black" Height="5"/>
 
   <Button Content="Hello world">
     <Button.Template>
       <ControlTemplate TargetType="{x:Type Button}">
         <ContentPresenter Content="{Binding RelativeSource
           ={RelativeSource TemplatedParent}, Path=Content}" />・・・(3)
       </ControlTemplate>
     </Button.Template>
   </Button>
 
 </StackPanel>
---レンダリング結果
#ref(RenderingResultOfRelativeSource.png,left,nowrap,RelativeSource)

--説明
---(1) では、TextBlock要素自身のFontFamilyプロパティを取得して、自身のTextプロパティに設定している。
---(2) では、親要素(AncestorType 属性に指定されているStackPanel型)を検索し、Orientationプロパティを取得して、自身のTextプロパティに設定している。
---(3) では、TemplatedParent 属性により、[[テンプレート>#o64ea160]]を適用しているControlTemplate(ここでは、ControlTemplateであるButton要素)の~
[[Contentプロパティ>#gc84bde8]]を取得し、ContentPresenterクラスの[[Contentプロパティ>#gc84bde8]]に設定している。

***コントロールと「テンプレート」内の各要素の関係 [#fce360c6]
以上を纏めた、コントロールと「テンプレート」内の各要素の関係は、次のようになる。
***参考 [#s29b90e0]
-MSDN > Windows Presentation Foundation
--> データ > データ バインディング > データ テンプレートの概要~
http://msdn.microsoft.com/ja-jp/library/ms742521.aspx

-ContentControlコントロール
--ContentControl全体の外観のカスタマイズ~
ContentControlの(Control.)Templateプロパティには、ControlTemplateクラスを設定する。
---各種プロパティの表示方法~
各種プロパティを表示するための要素をControlTemplateクラスに含める。
---Contentプロパティの表示方法~
ContentControl.Contentプロパティを表示する
ContentPresenterクラスをControlTemplateクラスに含める。
--ContentControlのContentプロパティのデータ表示の外観のカスタマイズ~
ContentControl.ContentTemplateプロパティには、DataTemplateクラスを設定する。
---各種プロパティの表示方法~
各種プロパティを表示するための要素をDataTemplateクラスに含める。
-WPF4.5入門 - かずきのBlog@hatena
--その47 「コンテンツモデル」~
http://blog.okazuki.jp/entry/2014/08/25/164331
--その52 「コントロールテンプレート」~
http://blog.okazuki.jp/entry/2014/09/07/195335

-ItemsControlコントロール
--ItemsControl全体の外観のカスタマイズ~
ItemsControlの(Control. )Templateプロパティには、ControlTemplateクラスを設定する。
---各種プロパティの表示方法~
各種プロパティを表示するための要素をControlTemplateクラスに含める。
---Itemsプロパティの表示方法~
ItemsControl.Itemsプロパティを表示するItemsPresenterクラスをControlTemplateクラスに含める。
--ItemsControlのItemsプロパティのデータ表示の外観のカスタマイズ~
ItemsControl.ItemTemplateプロパティには、DataTemplateクラスを設定する。
---各種プロパティの表示方法~
各種プロパティを表示するための要素をDataTemplateクラスに含める。
-WPFコントロールテンプレートとデータテンプレートの違い | tocsworld~
https://tocsworld.wordpress.com/2014/09/28/wpf%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC/

同じ要領で、コントロールによってはヘッダやセル専用の「テンプレート」プロパティが存在し、「外観」のカスタマイズを行うことができる。

**テンプレートの例 [#f9a8fb1a]
***ContentControlのテンプレート(ControlTemplate)の例 [#f0a5ccc8]

-XAML
--以下は、ControlTemplateとContentPresenterを使用したContentControl(Button)コントロールの例である。
 <Grid>
   <Button Margin="5" Width="100" Height="100" Content="ボタン">
     <Button.Template>
       <ControlTemplate TargetType="Button">
         <Grid>
           <Rectangle Fill="Blue"/>
           <Ellipse Fill="Red"/>
           <ContentPresenter
             HorizontalAlignment="Center"
             VerticalAlignment="Center"/>
         </Grid>
       </ControlTemplate>
     </Button.Template>
   </Button>
 </Grid>
--上記のContentPresenterを、「マークアップ拡張」のTemplateBindingに書き換えた例
 <Grid>
   <Button Margin="5" Width="100" Height="100" Content="ボタン">
     <Button.Template>
       <ControlTemplate TargetType="Button">
         <Grid>
           <Rectangle Fill="Blue"/>
           <Ellipse Fill="Red"/>
           <TextBlock
             Text="{TemplateBinding Content}"
             HorizontalAlignment="Center" VerticalAlignment="Center"/>
         </Grid>
       </ControlTemplate>
     </Button.Template>
   </Button>
 </Grid>
--上記のTemplateBindingを、「マークアップ拡張」のRelativeSourceに書き換えた例。~
なお、RelativeSourceの場合、TargetType属性を消しても上手く動作する現象を確認できた。
 <Grid>
   <Button Margin="5" Width="100" Height="100" Content="ボタン">
     <Button.Template>
       <ControlTemplate>
         <Grid>
           <Rectangle Fill="Blue"/>
           <Ellipse Fill="Red"/>
           <TextBlock
             Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"
             HorizontalAlignment="Center" VerticalAlignment="Center"/>
         </Grid>
       </ControlTemplate>
     </Button.Template>
   </Button>
 </Grid>

-レンダリング結果
#ref(RenderingResultOfControlTemplate.png,left,nowrap,ContentControlのControlTemplate)

-スタイル化
--「テンプレート」は、以下のように「スタイル」に組み込むことも可能である。
---XAML
 <Window.Resources>
   <Style x:Key="buttonTemplate" TargetType="Button">
     <Setter Property="Template">
       <Setter.Value>
         <ControlTemplate TargetType="Button">
           <Grid>
             <Rectangle Fill="Blue"/>
             <Ellipse Fill="Red"/>
             <ContentPresenter
               HorizontalAlignment="Center"
               VerticalAlignment="Center"/>
           </Grid>
         </ControlTemplate>
       </Setter.Value>
     </Setter>
   </Style>
 </Window.Resources>
 <StackPanel Orientation="Vertical">
   <Button Margin="5" Width="100" Height="100">ボタン1</Button>
   <Button Margin="5" Width="100" Height="100">ボタン2</Button>
   <Button Margin="5" Width="100" Height="100"
     Style="{StaticResource buttonTemplate}">ボタン3</Button>
 </StackPanel>
---レンダリング結果
#ref(RenderingResultOfStyleTemplate1.png,left,nowrap,ControlTemplateのスタイル化 (1))

--なお、x:Keyを設定しなければ、TargetType属性により、~
「スタイル」は指定の型(ここではButtonコントロール)、全体に適用される。
---XAML
 <Window.Resources>
   <Style TargetType="Button">
     <Setter Property="Template">
       <Setter.Value>
         <ControlTemplate TargetType="Button">
           <Grid>
             <Rectangle Fill="Blue"/>
             <Ellipse Fill="Red"/>
             <ContentPresenter
               HorizontalAlignment="Center"
               VerticalAlignment="Center"/>
           </Grid>
         </ControlTemplate>
       </Setter.Value>
     </Setter>
   </Style>
 </Window.Resources>
 <StackPanel Orientation="Vertical">
   <Button Margin="5" Width="100" Height="100">ボタン1</Button>
   <Button Margin="5" Width="100" Height="100">ボタン2</Button>
   <Button Margin="5" Width="100" Height="100">ボタン3</Button>
 </StackPanel>
---レンダリング結果
#ref(RenderingResultOfStyleTemplate2.png,left,nowrap,ControlTemplateのスタイル化 (2))

-リソース化
--「テンプレート」と「スタイル」を別々の「リソース」として定義し、~
StaticResource参照の「マークアップ拡張」により~
「テンプレート」を「スタイル」に組み込むことも可能である。
---XAML
 <Window.Resources>
   <ControlTemplate x:Key="buttonTemplate" TargetType="Button">
     <Grid>
       <Rectangle Fill="Blue"/>
       <Ellipse Fill="Red"/>
       <ContentPresenter
         HorizontalAlignment="Center"
         VerticalAlignment="Center"/>
     </Grid>
   </ControlTemplate>
   <Style TargetType="Button">
     <Setter Property="Template" Value="{StaticResource buttonTemplate}"/>
   </Style>
 </Window.Resources>
 <StackPanel Orientation="Vertical">
   <Button Margin="5" Width="100" Height="100">ボタン1</Button>
   <Button Margin="5" Width="100" Height="100">ボタン2</Button>
   <Button Margin="5" Width="100" Height="100">ボタン3</Button>
 </StackPanel>
--以下、同様に、「ディクショナリ ファイル」を使用して、CSSファイルのように、~
「テンプレート」を外部ファイルに定義することも可能である。
---XAML
 <Window.Resources>
   <ResourceDictionary Source="TemplateStyleDictionary.xaml"/>
 </Window.Resources>
 <StackPanel Orientation="Vertical">
   <Button Margin="5" Width="100" Height="100">ボタン1</Button>
   <Button Margin="5" Width="100" Height="100">ボタン2</Button>
   <Button Margin="5" Width="100" Height="100">ボタン3</Button>
 </StackPanel>
---XAML ( 外部ディクショナリ ファイル : TemplateStyleDictionary.xaml
 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   <ControlTemplate x:Key="buttonTemplate" TargetType="Button">
     <Grid>
       <Rectangle Fill="Blue"/>
       <Ellipse Fill="Red"/>
       <ContentPresenter
         HorizontalAlignment="Center"
         VerticalAlignment="Center"/>
     </Grid>
   </ControlTemplate>
   <Style TargetType="Button">
     <Setter Property="Template" Value="{StaticResource buttonTemplate}"/>
   </Style>
 </ResourceDictionary>
--レンダリング結果
#ref(RenderingResultOfStyleTemplate2.png,left,nowrap,ControlTemplateのスタイル化 (2))

***ContentControlのテンプレート(DataTemplate)の例 [#i4243f6b]
-以下は、ControlTemplate + ContentPresenterとDataTemplateを使用したContentControl(Button)コントロールの例である。

--XAML
 <Grid>
   <Button Content="Click Here"
     Margin="5" Width="100" Height="100">
     <Button.Template>
       <ControlTemplate TargetType="Button">
         <Grid>
           <Rectangle Fill="Blue"/>
           <Ellipse Fill="Red"/>
           <ContentPresenter
             HorizontalAlignment="Center"
             VerticalAlignment="Center"/>
         </Grid>
       </ControlTemplate>
     </Button.Template>
     <Button.ContentTemplate>
       <DataTemplate>
         <Grid>
           <TextBlock Text="{Binding}"/>
         </Grid>
       </DataTemplate>
     </Button.ContentTemplate>
   </Button>
 </Grid>

--レンダリング結果
#ref(RenderingResultOfDataTemplateOfContentControl.png,left,nowrap,ContentControlのDataTemplate)

--上記の通り、DataTemplate内でContentプロパティのデータを使用する場合は、"{Binding}"と記述するだけで良い。

-DataTemplateのポイント
--通常、ContentControl内にはContentControl.Contentプロパティを表示するだけの場合が多いので、~
ControlTemplateだけで事足りることが多く、DataTemplateの利用機会は少ない。

--なお、ControlTemplate + ContentPresenterとDataTemplateは必ずしも併用しなくても良い(DataTemplateのみの利用も可能である)。
--なお、ControlTemplate + ContentPresenterとDataTemplateは、~
必ずしも併用しなくても良い(DataTemplateのみの利用も可能である)。

--DataTemplate内でContentプロパティ以外のデータを使用する場合は、例えば、
 <TextBlock Text="{Binding RelativeSource={RelativeSource Self}, Path=xxxx}"/>

>>などの記述方法がある。

***ItemsControlのテンプレート(DataTemplate)の例 [#p680d343]
-以下は、ItemsControl.ItemTemplateプロパティを使用したListBoxコントロールの例である。

--これは、前述のサンプルの改良版である。
---[[Itemsプロパティ>#v7960713]]
---[[データ バインディングの基礎>#h0ae3316]]

--基本的に、~
ItemsControlコントロールに「データ バインディング」を行った際の「外観」のカスタマイズには、~
ItemsControl.ItemTemplateプロパティへ、DataTemplateを指定することで行う。

--コード

---XAML
 <Grid>
   <StackPanel x:Name="stackPanel1">
     <ListBox x:Name="ListBox1" ItemsSource="{Binding}">
       <ListBox.ItemTemplate>
         <DataTemplate>
           <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
             <StackPanel Orientation="Horizontal" Height="120" Width="250">
               <Image Height="100" Source="{Binding Path=[Image]}" />
               <TextBlock Text="{Binding Path=[Text]}"  VerticalAlignment="Center" />
             </StackPanel>
           </Border>
         </DataTemplate>
       </ListBox.ItemTemplate>
     </ListBox>
   </StackPanel>
 </Grid>

---コード ビハインド
 public Window1() {
   InitializeComponent();
 
   List<Dictionary<string, string>> lst
     = new List<Dictionary<string, string>>();
 
   Dictionary<string, string> dic = null;
 
   dic = new Dictionary<string, string>();
   dic["Image"] = @".\Blue hills.jpg";
   dic["Text"] = "Blue hills";
   lst.Add(dic);
 
   dic = new Dictionary<string, string>();
   dic["Image"] = @".\Sunset.jpg";
   dic["Text"] = "Sunset";
   lst.Add(dic);
 
   dic = new Dictionary<string, string>();
   dic["Image"] = @".\Water lilies.jpg";
   dic["Text"] = "Water lilies";
   lst.Add(dic);
 
   dic = new Dictionary<string, string>();
   dic["Image"] = @".\Winter.jpg";
   dic["Text"] = "Winter";
   lst.Add(dic);
 
   this.stackPanel1.DataContext = lst;
 }

---補足~
補足となるが、選択したオブジェクトは、以下のコードで取得できる。
 Dictionary<string, string> dic = (Dictionary<string, string>)this.ListBox1.SelectedValue;

-なお、「バインディング ソース」にDataTableを使用する場合は、次のように記述できる。

--DataTableのDataColumnのColumnNameプロパティをPath属性に指定する際は、~
「通常のプロパティの場合の記述方法」・「インデクサの場合の記述方法」の両方の指定が可能である。

--また、ここでは、「テンプレート」を「リソース」として定義し、StaticResource参照により「スタイル」に指定している。

--コード

---XAML
 <Window.Resources>
   <DataTemplate x:Key="listBoxStyle">
     <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
       <StackPanel Orientation="Horizontal" Height="120" Width="250">
         <Image Height="100" Source="{Binding Path=Image}" /> ・・・ 通常のプロパティの場合の記述方法
         <TextBlock Text="{Binding Path=[Text]}"  VerticalAlignment="Center" /> ・・・ インデクサの場合の記述方法
       </StackPanel>
     </Border>
   </DataTemplate>
 </Window.Resources>
 <Grid>
   <StackPanel x:Name="stackPanel1">
     <ListBox x:Name="ListBox1"
       ItemsSource="{Binding}" ItemTemplate="{StaticResource listBoxStyle}"/>
   </StackPanel>
 </Grid>

---コード ビハインド
 public Window1() {
   InitializeComponent();
 
   DataTable dt = new DataTable();
 
   dt.Columns.Add(new DataColumn("Image"));
   dt.Columns.Add(new DataColumn("Text"));
 
   DataRow dr = null;
 
   dr = dt.NewRow();
   dr["Image"] = @".\Blue hills.jpg";
   dr["Text"] = "Blue hills";
   dt.Rows.Add(dr);
 
  ・・・
 
   dr = dt.NewRow();
   dr["Image"] = @".\Winter.jpg";
   dr["Text"] = "Winter";
   dt.Rows.Add(dr);
 
   this.stackPanel1.DataContext = dt;
 }

---補足~
補足となるが、選択したオブジェクトは、以下のコードで取得できる。
 DataRow dr = (DataRow)this.ListBox1.SelectedValue;

-レンダリング結果
#ref(RenderingResultOfDataTemplateOfItemsControl.png,left,nowrap,ItemsControlのDataTemplate)

***ItemsControl(DisplayMemberPath, SelectedValuePath)の例 [#q9e7a454]
-ここまで、ItemsControl.ItemTemplateプロパティへ、DataTemplateを指定する方法について述べたが、~
代表的なItemsControlコントロールであるListBoxやComboBox(Selector から派生するクラス)は、~
DisplayMemberPath、SelectedValuePathなどの属性を持っている。

-このため、単純な表示であればItemsControl.ItemTemplateプロパティへ、DataTemplateを指定しなくても、~
「データ バインディング」したオブジェクトから「表示項目」と「データ項目」を分離できる。

-以下、その例を示す。
--XAML
 <Grid>
   <StackPanel x:Name="stackPanel1">
     <ListBox x:Name="ListBox1" ItemsSource="{Binding}"
       SelectedValuePath="Value" DisplayMemberPath="Display" />
     <Button Click="Button_Click">選択値</Button>
   </StackPanel>
 </Grid>
--コード ビハインド
 public Window1() {
   InitializeComponent();
 
   DataTable dt = new DataTable();
   dt.Columns.Add(new DataColumn("Value"));
   dt.Columns.Add(new DataColumn("Display"));
 
   DataRow dr = null;
 
   dr = dt.NewRow();
   dr["Value"] = "0001";
   dr["Display"] = "0001の表示";
   dt.Rows.Add(dr);
 
  ・・・
 
   dr = dt.NewRow();
   dr["Value"] = "0004";
   dr["Display"] = "0004の表示";
   dt.Rows.Add(dr);
 
   this.stackPanel1.DataContext = dt;
 }
--レンダリング結果
#ref(RenderingResultOfListBox1.png,left,nowrap,SelectedValuePath,DisplayMemberPath属性の利用 (1))

-DisplayMemberPath属性に指定されたデータが表示項目となり、~
SelectedValuePath属性に指定されたデータがSelectedValueプロパティで取得される、選択時のデータ項目となる。~
以下は、選択されたデータを取得するコードの例である。

--コード ビハインド
 private void Button_Click(object sender, RoutedEventArgs e) {
   MessageBox.Show(this.ListBox1.SelectedValue.ToString());
 }
--選択されたデータ
#ref(RenderingResultOfListBox2.png,left,nowrap,SelectedValuePath,DisplayMemberPath属性の利用 (2))

***その他のItemsControlのテンプレートの例 [#eb36bade]
-ControlTemplateを使用したItemsControl
--以下は、ControlTemplateを使用したItemsControl(ListBox)コントロールの例である。
--通常、ItemsControlではDataTemplateだけで事足りることが多いので、ControlTemplateの利用機会は少ないが、~
ここではControlTemplate内でItemsPresenterを使用してItemsプロパティのデータの中央揃えに利用している。
--XAML
 <Grid>
   <ListBox>
     <ListBox.Template>
       <ControlTemplate>
         <ItemsPresenter Margin="5" HorizontalAlignment="Center"/>
       </ControlTemplate>
     </ListBox.Template>
     <ListBoxItem>1</ListBoxItem>
     <ListBoxItem>2</ListBoxItem>
     <ListBoxItem>3</ListBoxItem>
   </ListBox>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfControlTemplateOfItemsControl.png,left,nowrap,ItemsControlとControlTemplate)

-ItemsPanelTemplateを使用したItemsControl
--Itemsプロパティのデータの並び(レイアウト)は、~
ItemsControl.ItemsPanel プロパティにItemsPanelTemplate を設定することで変更できる。
--ここではStackPanelを使用し、各アイテムの並びを横並びにしている。
--XAML
 <Grid>
   <ListBox>
     <ListBox.Template>
       <ControlTemplate TargetType="ListBox">
         <ItemsPresenter Margin="5" HorizontalAlignment="Center"/>
       </ControlTemplate>
     </ListBox.Template>
     <ListBox.ItemsPanel>
       <ItemsPanelTemplate>
         <StackPanel Orientation="Horizontal"/>
       </ItemsPanelTemplate>
     </ListBox.ItemsPanel>
     <ListBoxItem>1</ListBoxItem>
     <ListBoxItem>2</ListBoxItem>
     <ListBoxItem>3</ListBoxItem>
   </ListBox>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfItemsPanelTemplate.png,left,nowrap,ItemsControlとItemsPanelTemplate)

--参考
---MSDN > .NET Frameworkクラス ライブラリ~
● System.Windows.Controls.ItemsControl.ItemsPanelプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemscontrol.itemspanel.aspx~
● System.Windows.Controls.ItemsPanelTemplateクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.controls.itemspaneltemplate.aspx

-ヘッダの追加(ControlTemplate)
--ItemsControlでは、ControlTemplateは(繰り返し項目以外の)ヘッダなどの「外観」を作成するなどの用途で使用することが可能である。
--以下、ヘッダをControlTemplateで実装し、データをDataTemplateで実装した例である。
--コード
---XAML
 <Grid>
   <ListBox Name="listBox1" ItemsSource="{Binding}">
     <ListBox.Template>
       <ControlTemplate>
         <StackPanel>
           <StackPanel  Orientation="Horizontal" Background="Gray">
             <TextBlock Width="100" Text="ヘッダ1"/>
             <TextBlock Width="100" Text="ヘッダ2"/>
           </StackPanel>
           <ItemsPresenter/>	・・・ItemsPresenterを忘れないよう設定する。
         </StackPanel>
       </ControlTemplate>
     </ListBox.Template>
     <ListBox.ItemTemplate>
       <DataTemplate>
         <StackPanel  Orientation="Horizontal">
           <TextBlock Width="100" Text="{Binding Path=[data1]}"/>
           <TextBlock Width="100" Text="{Binding Path=[data2]}"/>
         </StackPanel>
       </DataTemplate>
     </ListBox.ItemTemplate>
   </ListBox>
 </Grid>
---コード ビハインド
 public Window1() {
   InitializeComponent();
 
   List<Dictionary<string, string>> lst = new List<Dictionary<string, string>>();
   Dictionary<string, string> dic = null;
 
   dic = new Dictionary<string, string>();
   dic["data1"] = "データ11";
   dic["data2"] = "データ11";
   lst.Add(dic);
 
   dic = new Dictionary<string, string>();
   dic["data1"] = "データ21";
   dic["data2"] = "データ22";
   lst.Add(dic);
 
   this.listBox1.DataContext = lst; 
 }
--レンダリング結果
#ref(RenderingResultOfControlTemplateOfItemsControlWithHeader.png,left,nowrap,ControlTemplateによるヘッダの追加)

--グリッド系のコントロールには、ヘッダ専用の「テンプレート」が準備されているものもある。

-各種テンプレートの組み合わせ~
以下は、DataTemplate、ControlTemplate、ItemsPanelTemplateを使用し、~
[[ItemsControlのテンプレート(DataTemplate)の例>#p680d343]]を書き直した~
ItemsControl(ListBox)コントロールの例である(中央揃え+横並び)。
--コード
---XAML
 <Grid>
   <StackPanel x:Name="stackPanel1">
     <Button x:Name="button1" Click="button1_Click">選択</Button>
     <ListBox x:Name="ListBox1" ItemsSource="{Binding}">
 
       <ListBox.Template>
         <ControlTemplate>
           <ItemsPresenter Margin="5" HorizontalAlignment="Center"/>
         </ControlTemplate>
       </ListBox.Template>
 
       <ListBox.ItemsPanel>
         <ItemsPanelTemplate>
           <StackPanel Orientation="Horizontal"/>
         </ItemsPanelTemplate>
       </ListBox.ItemsPanel>
 
       <ListBox.ItemTemplate>
         <DataTemplate>
           <Border BorderBrush ="Black" BorderThickness ="1" Margin="5">
             <StackPanel Orientation="Horizontal" Height="120" Width="250">
               <Image Height="100" Source="{Binding Path=[Image]}" />
               <TextBlock Text="{Binding Path=[Text]}"  VerticalAlignment="Center" />
             </StackPanel>
           </Border>
         </DataTemplate>
       </ListBox.ItemTemplate>
 
     </ListBox>
   </StackPanel>
 </Grid>
---コード ビハインド
 public Window1() {
   InitializeComponent();
 
   DataTable dt = new DataTable();
 
   dt.Columns.Add(new DataColumn("Image"));
   dt.Columns.Add(new DataColumn("Text"));
 
   DataRow dr = null;
 
   dr = dt.NewRow();
   dr["Image"] = @".\Blue hills.jpg";
   dr["Text"] = "Blue hills";
   dt.Rows.Add(dr);
 
  ・・・
 
   dr = dt.NewRow();
   dr["Image"] = @".\Winter.jpg";
   dr["Text"] = "Winter";
   dt.Rows.Add(dr);
 
   this.stackPanel1.DataContext = dt;
 }
 
 private void Button_Click(object sender, RoutedEventArgs e) {
   MessageBox.Show(this.ListBox1.SelectedValue.ToString());
 }
--レンダリング結果
#ref(RenderingResultOfVariousTemplatesOfItemsControl.png,left,nowrap,ItemsControlの各種テンプレートの組み合わせ利用)

***グリッド系コントロールの例 [#dcea1bb1]
-ヘッダ・セルのカスタマイズ~
以下、ListViewコントロールのヘッダとセルのカスタマイズの例を示す。
--コード
---XAML
 <Window.Resources>
   <Style x:Key="listViewItemStyle" TargetType="ListViewItem" >
     <Setter Property="BorderBrush" Value="Gray"/>
     <Setter Property="BorderThickness" Value="2"/>
   </Style>
   <DataTemplate x:Key="listViewHeaderTemplate">
     <TextBlock FontSize="16" Foreground="Navy" Text="{Binding}"/>
   </DataTemplate>
   <DataTemplate x:Key="listViewCellStyle">
     <Border BorderBrush ="Black" BorderThickness ="5" Margin="5">
       <Image Height="100" Source="{Binding Path=Image}" />
     </Border>
   </DataTemplate>
 </Window.Resources>
 <StackPanel x:Name="stackPanel1">
   <ListView x:Name="listView1" ItemsSource="{Binding}"
     ItemContainerStyle="{StaticResource listViewItemStyle}">
     <ListView.View>
       <GridView ColumnHeaderTemplate="{StaticResource listViewHeaderTemplate}">
         <GridViewColumn Header="名称" 
           DisplayMemberBinding="{Binding Path=Text}" />
         <GridViewColumn Header="画像"
           CellTemplate="{StaticResource listViewCellStyle}"/>
       </GridView>
     </ListView.View>
   </ListView>
 </StackPanel>
---コード ビハインド
 public Window1() {
   InitializeComponent();
 
   DataTable dt = new DataTable();
 
   dt.Columns.Add(new DataColumn("Image"));
   dt.Columns.Add(new DataColumn("Text"));
 
   DataRow dr = null;
 
   dr = dt.NewRow();
   dr["Image"] = @".\Blue hills.jpg";
   dr["Text"] = "Blue hills";
   dt.Rows.Add(dr);
 
  ・・・
 
   this.stackPanel1.DataContext = dt;
 }
--レンダリング結果
#ref(RenderingResultOfGridControlWithHeader.png,left,nowrap,ヘッダの追加(グリッド系コントロール))

--グリッド系のコントロール(ListView・GridView)は、以下のカスタマイズが可能である。
---GridViewColumn クラスを使用した列の定義、
---GridViewColumn.CellTemplate プロパティへの列「テンプレート」設定
---GridView.ColumnHeaderTemplate プロパティへのヘッダ「テンプレート」設定

-セルにComboBoxを入れる
--ListViewコントロールのセルにComboBoxを入れることも可能である。~
この場合、列「テンプレート」を定義して、GridViewColumn.CellTemplateプロパティへ設定すれば良い。
--この際、「データ バインディング」を使用してComboBoxを初期化する場合は、~
StaticResourceを使用した「データ バインディング」にて行う必要がある。~
このため、ComboBoxボックス毎に「リソース」に定義するクラス型を作成する必要がある。
--この処理を実装する際のポイントは、以下のとおりである。
---ComboBoxボックス毎に「リソース」に定義するクラス型を作成する必要があるので、~
基本クラスなどを用いて、このクラス型の定義を簡単に行えるようにする。
---上記で作成したComboBoxボックス毎に「リソース」に定義するクラス型にデータをロードする処理は、~
各クラスのコンストラクタに実装する必要があるが、3層C/S型システムなどでAPサーバからデータ取得を行う場合、~
ラウンドトリップが多くなってしまうことがあるため、集約してデータを取得できるように、処理を工夫する必要がある。
--サンプル~
https://github.com/OpenTouryoProject/SampleProgram/tree/master/UISubsystem/WPF/Cbx%20in%20DataGrid

*トリガ [#x73e9a3a]
-トリガは、
--Style 、ControlTemplate 、DataTemplate などの、~
UIElementの視覚化を指定するオブジェクトのプロパティとして設定し、
--「ある事象」をきっかけにして、そのUIElementの視覚設定を変更する

>ものである。

-トリガには、以下の3種類が存在し、それぞれ、きっかけとなる事象の種類が異なる。
--プロパティ トリガ~
きっかけ:上記の適用されているUIElementのプロパティの変更
--データ トリガ~
きっかけ:UIElementにバインドされたデータのプロパティの変更
--イベント トリガ~
きっかけ:上記の適用されているUIElementでハンドルできる「ルーティング イベント」の検知

-以下、それぞれのトリガについて説明する。

**プロパティ トリガ [#z60358ba]
-プロパティ トリガは、UIElementのプロパティ値に基づく。
-データトリガには、Triggerと、MultiTriggerの2つがある。

-以下は、プロパティ トリガとStyleを組み合わせて利用した例である。
--XAML
 <Window.Resources>
   <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
     <Setter Property="Background" Value="LightYellow" />
     <!--IsPressed = True で、背景色変更-->
     <Style.Triggers>
       <Trigger Property="IsPressed" Value="True">
         <Setter Property="Background" Value="LightBlue" />
       </Trigger>
     </Style.Triggers>
   </Style>
 
   <Style x:Key="ButtonStyle2" TargetType="{x:Type Button}">
     <Setter Property="Background" Value="LightYellow" />
     <!--IsMouseOver = True で、背景色変更-->
     <Style.Triggers>
       <Trigger Property="IsMouseOver" Value="True">
         <Setter Property="Background" Value="LightBlue" />
       </Trigger>
     </Style.Triggers>
   </Style>
 
   <Style x:Key="ButtonStyle3" TargetType="{x:Type Button}">
     <Setter Property="Background" Value="LightYellow" />
     <!--IsMouseOver、IsFocused = True で、背景色変更-->
     <Style.Triggers>
       <MultiTrigger>
         <MultiTrigger.Conditions>
           <Condition Property="IsMouseOver" Value="True"/>
           <Condition Property="IsFocused" Value="True"/>
         </MultiTrigger.Conditions>
         <Setter Property="Background" Value="LightBlue" />
       </MultiTrigger >
     </Style.Triggers>
   </Style>
 </Window.Resources>
 
 <Grid>
   <Grid.RowDefinitions>
             <RowDefinition />
             <RowDefinition />
             <RowDefinition />
   </Grid.RowDefinitions>
   <Button Style="{StaticResource ButtonStyle1}" Grid.Row="0" >Button(IsPressed)</Button>
   <Button Style="{StaticResource ButtonStyle2}" Grid.Row="1" >Button(IsMouseOver)</Button>
   <Button Style="{StaticResource ButtonStyle3}" Grid.Row="2" >Button(IsMouseOver & IsFocused)</Button>
 </Grid>
--レンダリング結果
#ref(RenderingResultOfPropertyTrigger.png,left,nowrap,プロパティ トリガ)

-参考
--MSDN > .NET Frameworkクラス ライブラリ
---> System.Windows.Triggerクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.trigger.aspx
---> System.Windows.MultiTriggerクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.multitrigger.aspx

**データ トリガ [#af3def31]
-データ トリガは、UIElementのプロパティ値ではなく、~
バインドされたデータのプロパティ値に基づく。
-データトリガには、DataTriggerと、MultiDataTriggerの2つがある。

-以下は、データ トリガとStyleを組み合わせて利用した例である。
--コード
---XAML
 <Window.Resources>
 
   <my:Places x:Key="PlacesData"/>
 
   <Style TargetType="ListBoxItem">
     <Style.Triggers>
 
       <!--DataTrigger(Condition×1)-->
       <!-- State = WA の行は文字色 = 赤-->
       <DataTrigger Binding="{Binding Path=State}" Value="WA">
         <Setter Property="Foreground" Value="Red" />
       </DataTrigger>
 
       <!--MultiDataTrigger(Condition×n)-->
       <!-- Name = Portland, State = OR の行は背景色 = 黄-->
       <MultiDataTrigger>
         <MultiDataTrigger.Conditions>
           <Condition Binding="{Binding Path=Name}" Value="Portland" />
           <Condition Binding="{Binding Path=State}" Value="OR" />
         </MultiDataTrigger.Conditions>
         <Setter Property="Background" Value="Yellow" />
       </MultiDataTrigger>
 
     </Style.Triggers>
   </Style>
 
   <DataTemplate DataType="{x:Type my:Place}">
     <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
       <TextBlock Width="20"/>
       <TextBlock Width="100" Text="{Binding Path=Name}"/>
       <TextBlock Width="20"/>
       <TextBlock Text="{Binding Path=State}"/>
     </StackPanel>
   </DataTemplate>
 
 </Window.Resources>
 
 <StackPanel>
   <TextBlock Margin="5" HorizontalAlignment="Center">Data Trigger Sample</TextBlock>
   <ListBox HorizontalAlignment="Stretch"
            ItemsSource="{Binding Source={StaticResource PlacesData}}"/>
 </StackPanel>
---コード ビハインド~
カスタムクラスであるPlaces(前述のXAMLのWindow.Resourcesに定義されている)は、~
(StaticResourceから)直接初期化できるように以下のように定義する。
 /// <summary>Place</summary>
 public class Place {
   /// <summary>名前</summary>
   private string _name;
 
   /// <summary>状態</summary>
   private string _state;
 
   /// <summary>名前</summary>
   public string Name {
     get { return _name; }
     set { _name = value; }
   }
 
   /// <summary>状態</summary>
   public string State {
     get { return _state; }
     set { _state = value; }
   }
 
   /// <summary>コンストラクタ</summary>
   public Place(string name, string state) {
     this._name = name;
     this._state = state;
   }
 }
 
 public class Places : ObservableCollection<Place> {
   /// <summary>コンストラクタで</summary>
   public Places() {
     this.Add(new Place("Bellevue", "WA"));
     this.Add(new Place("Gold Beach", "OR"));
     this.Add(new Place("Kirkland", "WA"));
     this.Add(new Place("Los Angeles", "CA"));
     this.Add(new Place("Portland", "ME"));
     this.Add(new Place("Portland", "OR"));
     this.Add(new Place("Redmond", "WA"));
     this.Add(new Place("San Diego", "CA"));
     this.Add(new Place("San Francisco", "CA"));
     this.Add(new Place("San Jose", "CA"));
     this.Add(new Place("Seattle", "WA"));
   }
 }
--レンダリング結果
#ref(RenderingResultOfDataTrigger.png,left,nowrap,データ トリガ)

-参考
--MSDN > .NET Frameworkクラス ライブラリ
---> System.Windows.DataTriggerクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.datatrigger.aspx
---> System.Windows.MultiDataTriggerクラス~
http://msdn.microsoft.com/ja-jp/library/system.windows.multidatatrigger.aspx

**イベント トリガ [#p908262c]
-通常、イベント トリガはアニメーション処理開始の指定のために使用する。
-これについては、「[[アニメーション>XAMLの書き方(2)#x6c21b91]]」を参照のこと。
-なお、イベント トリガはFrameworkElementにも指定することができる 。

-参考
--MSDN > .NET Frameworkクラス ライブラリ
---> System.Windows.FrameworkElement.Triggersプロパティ~
http://msdn.microsoft.com/ja-jp/library/system.windows.frameworkelement.triggers.aspx

----
Tags: [[:.NET開発]], [[:UIサブシステム]], [[:WPF/Silverlight, XAML]]


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS