6

DataContext に ViewModel を持つ親コンテナー ビューにプロパティをバインドしたいと考えています。

このコードは、親がConcreteClassViewの直接のインスタンスである場合に完全に機能します。

Property="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ty:ConcreteClassView}}, Path=DataContext.Name}"

ただし、基本クラスまたはインターフェイスを介して親を見つけようとすると、親が見つかりません。サンプル:

PropertyB="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ty:BaseClassView}}, Path=DataContext.Name}"

PropertyB="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ty:INamedElementView}}, Path=DataContext.Name}"

それを与える:

class ConcreteClassView : BaseClassView, INamedElementView { }

わかりました、 FindAncestorAncestorTypeが機能するために具象型が必要であると仮定しましょう。

しかし、基本クラスに基づいて、または特定のインターフェイスを実装するだけで先祖を見つけるための回避策はありますか?

なるほど。

4

1 に答える 1

8

FindAncestor、AncestorType は基本クラスで機能するため、仮定は間違っています。

ここに証拠があります:これはうまくいきます

<HeaderedContentControl Tag="ABC">
    <TextBlock Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
</HeaderedContentControl>

インターフェイスでも動作します (Button は ICommandSource を実装します)。

<Button Tag="ABC">
    <TextBlock Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ICommandSource}}" />
</Button>

(.NET 4.5 でテスト済み)

では、なぜあなたのコードが機能しないのでしょうか?

  1. バインド ターゲットと探している要素の間に、ビジュアル ツリーの ty:BaseClassView から派生した別の要素がある場合があります。

これは機能しません:

<HeaderedContentControl Tag="ABC">
    <Label>
        <TextBlock Text="{Binding Tag, RelativeSource={RelativeSource AncestorType=ContentControl}}" />
    </Label>
</HeaderedContentControl>

Label も ContentControl から継承されるため、この場合、Binding Source は Label です。

  1. ビジュアル ツリーが切断されている可能性があります。たとえば、ポップアップ コントロールは論理ツリーの一部ですが、独自のビジュアル ツリーを持っているため、ポップアップ内で RelativeSource FindAncestor を使用してポップアップ外の親を探すことはできません。Visibility="Collapsed" を設定すると、ビジュアル ツリーから要素が削除されることに注意してください。

デバッグする方法は?

  1. コンバーターを使用してバインディングをデバッグできます。RelativeSource といくつかの偽のコンバーターを指定し、パスを空のままにします。次に、コンバーターにブレークポイントを配置できます。値はバインディング ソースです。

  2. 要素のロードされたイベントをバインディングで使用して、すべての視覚的な親をデバッグ ウィンドウに書き込みます。

EDIT : Visual Studio 2015 では、ライブ ビジュアル ツリーエクスプローラーを使用して、実行時にビジュアル ツリーを検査できます (ブラウザーの開発者ツールが dom 要素を検査できるのと同様に)。このツールを使用すると、アプリケーションのバグを数秒で見つけることができます。

https://msdn.microsoft.com/en-us/library/mt270227.aspx

于 2015-04-03T11:55:08.850 に答える