web-dev-qa-db-ja.com

WPFで、Bindingが機能するのにTemplateBindingが機能しないのはなぜですか?

わかった…これで頭が引っ掻かれる。 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}"

だから何を与えるのですか?何が欠けていますか?

41
Mark A. Donohoe

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つです。

53
Matt West

TemplateBindingは双方向バインディングをサポートしていません。Bindingのみがサポートしています。 BindsTwoWayBeDefaultオプションを使用しても、双方向のバインドはサポートされません。

詳細は here ですが、要約すると:

ただし、TemplateBindingがデータを転送できるのは、テンプレート化された親からTemplateBindingを持つ要素への一方向のみです。反対方向または双方向でデータを転送する必要がある場合、TemplatedParentのRelativeSourceを使用したバインディングが唯一のオプションです。たとえば、双方向バインディングを使用する場合、テンプレート内のTextBoxまたはSliderとの相互作用は、テンプレート化された親のプロパティのみを変更します。

11
CodeNaked