akirikoの日記

2009-03-19

添付プロパティ その1

| 12:31

依存関係プロパティについて調べる過程で見つけた"依存関係プロパティと添付プロパティ 実験編"が気になったので、自分でも添付プロパティの実験をしてみた。


MSDN"添付プロパティの概要"を読めばわかるように、添付プロパティと依存関係プロパティは根本的に違う。

添付プロパティの目的は、次のものだ。

"添付プロパティの目的は、任意のオブジェクトに対して設定可能な一種のグローバル プロパティとして使用することです。"

だから、"いつ添付プロパティを作成するか"のセクションにも書いてあるように、

添付プロパティを作成するのは、プロパティを定義するクラス以外のクラスでプロパティを設定するための機構が必要な場合。


添付プロパティの概要の内容から、添付プロパティを単純なグローバルプロパティとして使うだけなら、

  • "Set[PropertyName]"があるだけで十分で、"Get[PropertyName]"は必要ない。
  • 添付プロパティが依存関係プロパティを参照する理由はない。
  • 添付プロパティを定義するクラスと設定するクラスの間には親子関係は必要ない。

と言えそうだ。


それを確かめるための実験コードを書いてみた。

下記のコードを実行すると、

起動時に以下のメッセージボックスが順に表示される。

start init

test1

test:System.Windows.Controls.Button

test2

test3

end init


そして、Checkボタンを押すと以下のメッセージボックスが順に表示される。

GetTest(button1):test1

GetTest(button2):test2

GetTest(button3):test3

_testString:test3


この実験から、以下のことが結論できる。

  • 添付プロパティの実体は、Set[PropertyName]メソッドの呼び出しに過ぎない
  • 依存関係プロパティは、Set[PropertyName]の実装の手段の一つ

これで、"依存関係プロパティの概要"の最後にある次の注意が理解できた。

"添付プロパティは、XAML で特殊な構文をサポートするプロパティの一種です。多くの場合、添付プロパティは共通言語ランタイム (CLR) プロパティと 1 対 1 で対応せず、依存関係プロパティであるとは限りません。"


あっ、たった今、依存関係プロパティや添付プロパティあたりのMSDNの文章の問題がわかった。意味と実装の区別が曖昧なんだ。

特に、添付プロパティを理解するために、依存関係プロパティを理解している必要があるというのは、誤解を招く表現だと思う。


次回は、依存関係プロパティを使わない添付プロパティでの子エレメントの操作の可能性を探ってみる。


コード

namespace WpfApplicationTest
{
    /// <summary>
    /// Window1.xaml の相互作用ロジック
    /// </summary>
    public partial class Window1 : Window
    {
        #region menbers
        static Dictionary<UIElement, string> _testStringDic = new Dictionary<UIElement,string>();
        static string _testString;
        #endregion // menbers

        public Window1()
        {
            MessageBox.Show("start init");
            InitializeComponent();
            MessageBox.Show("end init");
        }
        private void buttonCheckAttachedProperty_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("GetTest(button1):" + GetTest(button1));
            MessageBox.Show("GetTest(button2):" + GetTest(button2));
            MessageBox.Show("GetTest(button3):" + GetTest(button3));
            MessageBox.Show("_testString:" + _testString);
        }

        #region AttachedProperty
        public static void SetTest(UIElement element, string value)
        {
            _testStringDic[element] = value;
            _testString = value;
            MessageBox.Show(value);
        }
        public static string GetTest(UIElement element)
        {
            return _testStringDic[element];
        }
        #endregion // AttachedProperty
    }
    public class AttachedPropertyTest
    {
        public static void SetTest(UIElement element, string value)
        {
            MessageBox.Show(value + ":" + element.ToString());
        }
    }
}

XAML

<Window x:Class="WpfApplicationTest.Window1"
        x:Name="testWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:WpfApplicationTest="clr-namespace:WpfApplicationTest"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Button Height="30" Margin="30,10,100,0" Name="button1" VerticalAlignment="Top"
                WpfApplicationTest:Window1.Test ="test1"
                WpfApplicationTest:AttachedPropertyTest.Test="test">
            Button1
        </Button>
        <Button Height="30" Margin="30,50,100,0" Name="button2" VerticalAlignment="Top"
                WpfApplicationTest:Window1.Test ="test2">
            Button2
        </Button>
        <Button Height="30" Margin="30,90,100,0" Name="button3" VerticalAlignment="Top"
                WpfApplicationTest:Window1.Test ="test3">
            Button3
        </Button>
        <Button Height="30" Margin="30,150,100,0" Name="buttonCheckAttachedProperty" VerticalAlignment="Top"
                Click="buttonCheckAttachedProperty_Click">
            CheckAttachedProperty
        </Button>
    </Grid>
</Window>
トラックバック - http://d.hatena.ne.jp/akiriko/20090319