わかった…これで頭が引っ掻かれる。 2つのWPFコントロールがあります。1つはユーザーコントロール、もう1つはカスタムコントロールです。それらをUserFooとCustomFooと呼びましょう。 CustomFooのコントロールテンプレートでは、名前付きのパーツであるUserFooのインスタンスを使用しているため、テンプレートを適用した後で、そのインスタンスにアクセスできます。それはうまくいきます。
これで、UserFooとCustomFooの両方にText
プロパティが定義されています(独立して、つまりAddOwnerを使用した共有DPではありません。質問しないでください...)。このように宣言されています...
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(UserFoo), // The other is CustomFoo
new FrameworkPropertyMetadata(
null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
null,
null,
true,
UpdateSourceTrigger.PropertyChanged
)
);
特に、モードがTwoWayに設定され、UpdateSourceTriggerが両方ともPropertyChangedに設定されていることに注意してください。
したがって、CustomFooのスタイルテンプレートで、CustomFooのTextプロパティをソースとして内部のUserFooのTextプロパティにバインドします。通常、これは簡単です。 UserFooのtextプロパティを "{TemplateBinding Text}"に設定するだけですが、何らかの理由で片方向にしか機能しません(つまり、UserFooはCustomFooから正しく設定されますが、逆方向には設定されません)。ただし、テンプレートバインディングの代わりに相対ソースバインディングを使用すると、うまく機能します。えっと…なに?
// This one works
Text="{Binding Text, RelativeSource={RelativeSource AncestorType={local:CustomFoo}}, Mode=TwoWay}"
// As does this too...
Text="{Binding Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
// But not this one!
Text="{TemplateBinding Text}"
だから何を与えるのですか?何が欠けていますか?
MSDNでこのフォーラムの投稿を見つけました: http://social.msdn.Microsoft.com/Forums/en-US/wpf/thread/0bb3858c-30d6-4c3d-93bd-35ad0bb36bb4/
これはこう言います:
TemplateBindingは、テンプレートシナリオ用のバインディングの最適化された形式であり、
{Binding RelativeSource={RelativeSource TemplatedParent}}
OPからのメモ:ドキュメントに記載されている内容とは逆に、実際には次のようになります...
{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}
私はドキュメントに対して苦情を提出しましたが、彼らは常に一方向であることを示す文を追加しましたが、コード例にはまだモードがリストされていませんが、何もないよりはましだと思います。 )
TemplateBindingは、テンプレート化された親から、テンプレートバインドされているプロパティにデータを転送します。反対方向または双方向でデータを転送する必要がある場合は、ModedプロパティをOneWayToSourceまたはTwoWayに設定して、TemplatedParentのRelativeSourceでバインディングを作成します。
詳細: http://msdn.Microsoft.com/en-us/library/ms742882.aspx
Mode = OneWayは、TemplateBindingを使用する "最適化"の1つです。
TemplateBindingは双方向バインディングをサポートしていません。Bindingのみがサポートしています。 BindsTwoWayBeDefaultオプションを使用しても、双方向のバインドはサポートされません。
詳細は here ですが、要約すると:
ただし、TemplateBindingがデータを転送できるのは、テンプレート化された親からTemplateBindingを持つ要素への一方向のみです。反対方向または双方向でデータを転送する必要がある場合、TemplatedParentのRelativeSourceを使用したバインディングが唯一のオプションです。たとえば、双方向バインディングを使用する場合、テンプレート内のTextBoxまたはSliderとの相互作用は、テンプレート化された親のプロパティのみを変更します。