前回:http://blogs.wankuma.com/kazuki/archive/2008/01/31/120275.aspx
間があいちゃったけど、その3では読み取り専用のDependencyPropertyを作ってみた。
今度は、添付プロパティを作ってみようと思う。
添付プロパティってのは、GridやDockPanelやValidationあたりで使われてる。
たとえば…
<Grid>
<Button Grid.Row="1" Grid.Column="2" Content="Sample" />
</Grid>
にあるGrid.RowやGrid.Columnとかがそれにあたる。
要は、ボタンとかには本来無いプロパティを無理矢理?付け足すようなものです。
こうすることで、例みたいな本来コントロールとは関係無いレイアウトに関する情報とかを柔軟に付け加えることができる。
因みにJavaのGUIライブラリの1つSWTではLayoutDataというプロパティをコントロールが持っているという感じの作りになってたと思う。
将来的にレイアウト以外の情報を付け足そうと思うと、コントロールの基本クラスに手が入るような感じかな。
添付プロパティだと、そこらへんが割りと柔軟に拡張できるようになってる。
さて、添付プロパティですが、基本的に今までやってきた依存プロパティと大差無いです。
違いといえば、DependencyProperty.Registerで登録するかDependencyProperty.RegisterAttachedで登録するか…。
Personクラスに対していい例が思いつかなかったので、住所情報を添付プロパティでくっつけるようにしてみた。
public class Person : DependencyObject
{
// 今までと同じなので省略
}
// 別にstatic classじゃなくてもいい。当然DependencyObjectから派生したクラスでもOK
public static class PersonOptions
{
// DependencyObject.RegisterAttachedメソッドを呼ぶ以外は添付プロパティと同じ
public static readonly DependencyProperty AddressProperty =
DependencyProperty.RegisterAttached("Address", typeof(string), typeof(PersonOptions));
// staticなSetAddressやGetAddressというメソッドが対応するメソッド
public static void SetAddress(DependencyObject target, string value)
{
target.SetValue(AddressProperty, value);
}
public static string GetAddress(DependencyObject target)
{
return (string) target.GetValue(AddressProperty);
}
}
staticなSet~ Get~というメソッドを定義してるところ以外はあんまり変わらないと思う。
Set~ Get~というメソッドの中も、RegisterAttachedメソッドで帰ってきたDependencyProeprtyのインスタンスをキーにSetValue GetValueをしているだけ。
一緒だね。
早速これを使うサンプルをこさえてみた。
class Program
{
static void Main(string[] args)
{
var p = new Person();
p.Name = "田中 麻呂";
// 添付プロパティ!
PersonOptions.SetAddress(p, "東京都");
Console.WriteLine(p.Name);
// 添付プロパティ!
Console.WriteLine(PersonOptions.GetAddress(p));
}
}
何も面白く無いサンプルですが…。
ちなみに、このPersonクラスのインスタンスpと同じように、名前に田中 麻呂 添付プロパティのAddressに東京都をセットされたものを作ることをXAMLで書くと下のようになります。
<p:Person xmlns:p="clr-namespace:DependencyObjectSample;assembly=DependencyObjectPropertySample"
Name="田中 麻呂"
p:PersonOptions.Address="東京都"/>
これをPerson.xamlという名前で埋め込まれたリソースに設定する。それを読み込んで表示するプログラムは下のような感じ。
class Program
{
static void Main(string[] args)
{
var p = XamlReader.Load(
typeof(Program).Assembly.GetManifestResourceStream(
"DependencyPropertySample.Person.xaml")) as Person;
Console.WriteLine(p.Name);
Console.WriteLine(PersonOptions.GetAddress(p));
}
}
どちらも実行結果は下のようになる。PropertyChangeとかCoerceValueとかで出力してるものは除外してる。
田中 麻呂様
東京都
ちなみに、昔書いた自分の記事が参考になった。
当時は添付プロパティとかよく知らなかったわ。
DependencyObjectについてはここらへんで終了かな?ネタ切れ。