前回は、プロパティ要素構文を見ました。
今回は、WPF の XAML でよく登場する添付プロパティを整理します。
添付プロパティは、最初に見ると少し不思議な構文です。
<Button Grid.Row="1"
Grid.Column="2"
Content="保存" />
Button に Grid.Row や Grid.Column というプロパティがあるように見えます。しかし、これは通常のプロパティではありません。
Grid.Row や Grid.Column は、Grid が提供する添付プロパティです。
通常のプロパティとの違い
通常のプロパティは、その要素自身が持っている値です。
<Button Content="保存"
Width="120"
Height="32" />
この例では、Content、Width、Height はボタン自身のプロパティです。
一方、次の指定は少し違います。
<Button Grid.Row="1"
Content="保存" />
Grid.Row は、ボタン自身の通常プロパティではありません。Grid の中で、このボタンをどの行に置くかを示す追加情報です。
つまり、添付プロパティは「ある型が、別の要素に対して追加情報を持たせる」ための仕組みです。
Grid.Row と Grid.Column
もっともよく使う添付プロパティの例は、Grid.Row と Grid.Column です。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0"
Grid.Column="0"
Text="名前" />
<TextBox Grid.Row="0"
Grid.Column="1" />
<Button Grid.Row="1"
Grid.Column="1"
Content="保存" />
</Grid>
Grid は、子要素を行と列に配置するパネルです。
そのため、子要素ごとに「何行目か」「何列目か」という情報が必要です。
この情報を、子要素に対して次のように書きます。
Grid.Row="1"
Grid.Column="1"
ここで大切なのは、Grid.Row はボタンの見た目そのものを表す値ではなく、親である Grid が配置に使う情報だということです。
Canvas.Left と Canvas.Top
添付プロパティは、Canvas でも使われます。
<Canvas>
<Button Canvas.Left="20"
Canvas.Top="40"
Content="移動" />
</Canvas>
Canvas は、座標を指定して子要素を配置するパネルです。
Canvas.Left は左からの距離、Canvas.Top は上からの距離を表します。
この場合も、Button 自身が Canvas.Left という通常プロパティを持っているわけではありません。Canvas が子要素を配置するために使う追加情報です。
DockPanel.Dock
DockPanel では、子要素を上下左右のどこに固定するかを指定します。
<DockPanel>
<Button DockPanel.Dock="Top"
Content="上" />
<Button DockPanel.Dock="Bottom"
Content="下" />
<TextBox />
</DockPanel>
DockPanel.Dock は、子要素をどの方向に配置するかを示します。
このように、添付プロパティは特にレイアウトパネルでよく使われます。親のパネルが子要素をどう扱うかを、子要素側に書いていると考えると分かりやすくなります。
添付プロパティの形
添付プロパティは、属性として書く場合、次の形になります。
所有者の型.プロパティ名="値"
たとえば、次のような形です。
| 添付プロパティ | 意味 |
|---|---|
Grid.Row | Grid 内での行番号 |
Grid.Column | Grid 内での列番号 |
Grid.RowSpan | Grid 内で何行分にまたがるか |
Grid.ColumnSpan | Grid 内で何列分にまたがるか |
Canvas.Left | Canvas 内で左からの距離 |
Canvas.Top | Canvas 内で上からの距離 |
DockPanel.Dock | DockPanel 内で固定する方向 |
点の左側は、その添付プロパティを定義している型です。点の右側は、プロパティ名です。
コードで書いた場合
添付プロパティは、C# からも設定できます。
Button button = new Button
{
Content = "保存"
};
Grid.SetRow(button, 1);
Grid.SetColumn(button, 2);
XAML の次の記述は、
<Button Grid.Row="1"
Grid.Column="2"
Content="保存" />
C# では Grid.SetRow や Grid.SetColumn のようなメソッド呼び出しに対応します。
添付プロパティは、内部的には依存関係プロパティの仕組みを使っています。通常のプロパティのように見えますが、実際には Get と Set の静的メソッドを通じて値を扱います。
プロパティ要素構文との違い
前回見たプロパティ要素構文にも、点が含まれます。
<Button>
<Button.Content>
<TextBlock Text="保存" />
</Button.Content>
</Button>
今回の添付プロパティにも、点が含まれます。
<Button Grid.Row="1"
Content="保存" />
どちらも 型名.プロパティ名 の形に見えるため、混乱しやすいところです。
見分けるときは、どこに書かれているかに注目します。
| 構文 | 例 | 書かれる場所 |
|---|---|---|
| プロパティ要素構文 | <Button.Content> | 要素として書く |
| 添付プロパティ | Grid.Row="1" | 属性として書くことが多い |
また、意味も異なります。
プロパティ要素構文は、その要素自身のプロパティに複雑な値を設定します。
添付プロパティは、別の型が定義した追加情報を、その要素に設定します。
添付プロパティを読むコツ
添付プロパティを見たら、次のように読むと整理しやすくなります。
<Button Grid.Row="1"
Content="保存" />
これは、「ボタンの Grid 内での行番号は 1」と読みます。
<Button Canvas.Left="20"
Canvas.Top="40"
Content="移動" />
これは、「ボタンの Canvas 内での位置は左 20、上 40」と読みます。
<Button DockPanel.Dock="Top"
Content="上に配置" />
これは、「ボタンを DockPanel 内で上に固定する」と読みます。
点の左側にある型が、値をどう使うのかを考えると、意味が見えやすくなります。
まとめ
添付プロパティは、別の型が要素に追加情報を持たせるための仕組みです。
| 観点 | 通常のプロパティ | 添付プロパティ |
|---|---|---|
| 例 | Width="120" | Grid.Row="1" |
| 所有者 | 要素自身 | 点の左側の型 |
| 主な用途 | 要素自身の状態や見た目 | 親パネルでの配置情報など |
| コード上の形 | インスタンスプロパティ | 静的な Get/Set メソッド |
WPF のレイアウトでは、添付プロパティが頻繁に登場します。特に Grid.Row、Grid.Column、Canvas.Left、DockPanel.Dock は、XAML を読むうえで避けて通れません。
次回は、属性値の中に波かっこで書く、マークアップ拡張について整理します。