Ktouth Brand. on Web

け〜くんこと K.Ktouth のだらだらした日常と突発的に作るプログラムや読み物とかの雑多サイト



[2012年03月02日]

DependencyObject と Binding の落とし穴

2012年03月03日 08:28更新 筆者:K.Ktouth

今日一日、ちょっとした事で数時間原因究明に必死になってしまったトラブル。

DependencyObject の特徴といえば バインディング機能を使って能動的にデータを連結出来ることですが。DependencyObject だと Binding 側にちょっとした制限がありました。

<Window DataContext="{StaticResource Foobar}">
  <Window.Resources>
   <app:TextHelper Path="{Binding PathString}" />
  </Window.Resources>
  <TextBlock Text="{Binding PathString}" />
</Window>

上記は良くある Xaml コードの抜粋。app:TextHelper は DependencyObject から派生したクラス。
コードとしては全く問題ないものですが、TextBlock.Text プロパティには正しくバインディングされた値が適用されるのに対し、 app:TextHelper.Path には何も反映されません。

何の問題もないのに……と見えますが、実はバインディングに不足があります。ソースが指定されてないんですなあれ
ソースが見えないなら当然のごとく値が適用されることはありません。
ではなぜ TextBlock は値が適用されるのかというと FrameworkElement のデータ探索機能を経由して最終的に Window.DataContext プロパティに指定されたリソースを認識、それを暗黙のソースとして使用してくれるからです。この暗黙のソース指定機能は FrameworkElement およびその派生クラスで実装されていると言うわけです。

もちろん、以下のように

   <app:TextHelper Path="{Binding PathString, Source={StaticResource Foobar}}" />

と明示的にソース指定をしておけば問題ありませんが、これでは バインディング機構の魅力が半減してしまいます。
つーか、この機能、なぜ DependencyObject から実装しなかったんだろう……? 結局は WPF 専用の機能なのか…… orz

本日のリンク元
その他のリンク元
検索