かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

拡張されたプロパティメタデータ

依存関係プロパティのメタデータは、PropertyMetadataクラスの他に、PropertyMetadataクラスを継承したUIPropertyMetadataクラスや、FrameworkPropertyMetadataクラスがあります。UIPropertyMetadataクラスは、WPFのアニメーションを無効化にする機能を提供します。UIPropertyMetadataクラスを継承したFrameworkPropertyMetadataクラスは、FrameworkPropertyMetadataOptions列挙体によるレイアウトシステムへの影響の有無の設定や値の継承の有無の設定、データバインディングのデフォルト値の設定などWPFのフレームワークレベルの設定をサポートしています。カスタムコントロールを作成する場合などは通常FrameworkPropertyMetadataクラスを依存関係プロパティのメタデータに使用するといいでしょう。

FrameworkPropertyMetadataクラスの使用方法の一例として、子要素へ継承するプロパティの定義方法を以下に示します。

public class Person : FrameworkElement
{

    public static readonly DependencyProperty FirstNameProperty =
        DependencyProperty.Register(
            "FirstName", 
            typeof(string), 
            typeof(Person),
            new FrameworkPropertyMetadata(null));

    public string FirstName
    {
        get { return (string)GetValue(FirstNameProperty); }
        set { SetValue(FirstNameProperty, value); }
    }

    public static readonly DependencyProperty LastNameProperty =
        DependencyProperty.Register(
            "LastName", 
            typeof(string), 
            typeof(Person),
            // 子要素へ継承するプロパティ
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.Inherits));

    public string LastName
    {
        get { return (string)GetValue(LastNameProperty); }
        set { SetValue(LastNameProperty, value); }
    }

    public void AddChild(Person child)
    {
        this.AddLogicalChild(child);
    }
}

FrameworkElementという、DependencyObjectを間接的に継承したオブジェクトを継承してPersonクラスを作成しています。Personクラスには、名前を表すFirstName依存関係プロパティと、苗字を表すLastName依存関係プロパティがあります。苗字は、親子関係にある場合は同じものを使用するのが自然なので、FrameworkPropertyMetadataを使って、Inheritsを指定しています。親子関係の構築は、FrameworkElementクラスのAddLogicalChildメソッドを使って指定しています。

Personクラスの使用例を以下に示します。親と子のインスタンスを作って親のほうにだけLastNameプロパティを指定します。その状態で、親と子の両方のLastNameプロパティとFirstNameプロパティを表示しています。

[STAThread] // FrameworkElement使うのに必要
static void Main(string[] args)
{
    var parent = new Person { FirstName = "taro", LastName = "tanaka" };
    var child = new Person { FirstName = "jiro" };

    parent.AddChild(child);

    Console.WriteLine("{0} {1}", parent.LastName, parent.FirstName);
    Console.WriteLine("{0} {1}", child.LastName, child.FirstName);
}

実行すると以下のような結果になります。LastNameプロパティの値が継承されていることが確認できます。

tanaka taro
tanaka jiro

ここで紹介したFrameworkPropertyMetadataクラスは、カスタムコントロールを作成する場合でもない限り使用することはありませんが、カスタムコントロールを作成するときには、以下のリンクを読んでおくと役に立ちます。

過去記事