2.9 アタッチプロパティ
2.9.1 外部プロパティの適用
設計上、特定の条件下に置かれたときにのみオブジェクトに何らかの情報を付加させたいと考えることがあります。依存プロパティは、作成するオブジェクト自身に動的なプロパティを追加するものでしたが、プロパティを利用するクラスとは外部のオブジェクトに対して追加する特殊な依存プロパティのことをアタッチプロパティと呼びます。
アタッチプロパティは、依存プロパティの一種ですが、クラスの外部のオブジェクトに対して適用されることが前提となります。例えば、あなたが作成するクラスで、任意の数の UIElement オブジェクトを管理しなければならないとします。このとき、オブジェクトに対して、オブジェクトをどのように扱うかなどの付加情報を追加させたい場合にアタッチプロパティを利用します。
特定のクラスや条件下でしか使われないプロパティをクラスに直接追加するのは不適切です。上記のような場合は、UIElement オブジェクトを管理するクラスでのみ使用する付加情報を UIElement に追加するべきではありません。アタッチプロパティは、UIElement ではなく管理クラスで保有されますが、アタッチプロパティの値は UIElement オブジェクトに関連付けられます。
アタッチプロパティを利用するには DependencyProperty クラスの RegisterAttached() メソッドを使います。
public static DependencyProperty RegisterAttached ( string name, Type propertyType, Type ownerType )
name には、このアタッチプロパティの名前を、propertyType にはプロパティの型を、ownerType にはこのアタッチプロパティを所有する型を指定します。アタッチプロパティは、後述する XAML と呼ばれるマークアップ言語で使われることが想定されています。name に指定する名前は、XAML でアタッチプロパティを使用するときに使われます。
using System; using System.Windows; class TagManager { public static readonly DependencyProperty TagProperty; static TagManager() { TagProperty = DependencyProperty.RegisterAttached( "Tag", typeof(String), typeof(TagManager) ); } public static void SetTag(UIElement element, string value) { element.SetValue(TagProperty, value); } public static String GetTag(UIElement element) { return (string)element.GetValue(TagProperty); } } class Test { [STAThread] public static void Main() { Window wnd = new Window(); TagManager.SetTag(wnd, "Window1"); wnd.Title = TagManager.GetTag(wnd); Application app = new Application(); app.Run(wnd); } }
コード1は、アタッチプロパティを提供する TagManager クラスを作成しています。この TagManager クラスは、任意の UIElement オブジェクトに Tag というアタッチプロパティを追加することができる SetTag() メソッドと、設定した Tag プロパティを取得する GetTag() メソッドを公開しています。
このプログラムでは、Window オブジェクトに "Window1" という文字列の Tag プロパティを設定し、その後 GetTag() メソッドから設定した Tag プロパティを取得して Title プロパティに設定しているだけなので、特にこのアタッチプロパティが何か仕事をするわけではありません。本来ならば、Tag プロパティを使って何かをするのは Tag プロパティの保有者である TagManager クラスです。TagManager クラスが UIElement オブジェクトを使って何らかの作業を行うときに、Tag という付加情報を参考にしたい時にアタッチプロパティを用います。
一般的な設計では、アタッチプロティも通常の依存プロパティと同じように public static readonly 宣言のフィールドで公開されます。命名規則も、プロパティ名に Property という接尾辞を加えたものです。そして、外部のオブジェクトにアタッチプロパティを設定するための Set~() メソッドと Get~() メソッドを作成します。
class Owner { public static readonly DependencyProperty XXXProperty = DependencyProperty.RegisterAttached( "XXX", typeof(Object), typeof(Owner) ); public static void SetXXX(UIElement element, Object value) { ... } public static Object GetXXX(UIElement element) { ... } ... }
上記の XXX には、任意のプロパティ名が入ります。上記の設計によるアタッチプロパティは、WPF の一部のクラスでも用いられています。