35

ここで何が間違っていますか?:

 <GridViewColumn>
    <GridViewColumn.CellTemplate>
       <DataTemplate>
          <Button>
            <Button.ToolTip>
              <TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" />

これは単なる単純化された例であり、とにかく機能しません:) 実際には、ウィンドウの DataContext の範囲内にある別のプロパティから値を取得する必要があります。

助けてください。

4

4 に答える 4

82

ToolTip は VisualTree の一部ではないため、これは注意が必要です。ここでは、ContextMenus を使用した同じ問題に対するクールな解決策を示します。ToolTip と同じ方法でアクセスできます。

更新
悲しいことに、リンクがなくなっており、参照されている記事が見つかりません。
私が覚えている限り、参照されたブログでは、別の VisualTree の DataContext にバインドする方法が示されています。これは、ToolTip、ContextMenu、または Popup からバインドするときに必要になることがよくあります。

これを行う良い方法は、PlacementTarget の Tag プロパティ内で目的のインスタンス (ViewModel など) を提供することです。次の例では、ViewModel のコマンド インスタンスにアクセスするためにこれを行います。

<Button Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=Self}}">
  <Button.ContextMenu>
    <ContextMenu>
       <MenuItem Command="{Binding PlacementTarget.Tag.DesiredCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" .../>
    <ContextMenu>
  </Button.ContextMenu>
</Button>

私はそれをテストしておらず、前回これを行ったのは長い間です。うまくいかない場合はコメントしてください。

更新 2

この回答が書かれた元のリンクがなくなったので、archive.org にアクセスして、元のブログ エントリを見つけました。これは、ブログからの逐語的なものです。

WPF の ContextMenu は、ページ/ウィンドウ/コントロール自体のビジュアル ツリー内には存在しないため、データ バインディングは少し難しい場合があります。私はこれについてウェブ全体で高低を検索しましたが、最も一般的な答えは「コードビハインドでそれを行うだけ」のようです. 違う!私が XAML のすばらしい世界に足を踏み入れたのは、コード ビハインドでの作業に戻るためではありません。

これは、ウィンドウのプロパティとして存在する文字列にバインドできるようにする私の例です。

public partial class Window1 : Window
{
    public Window1()
    {
        MyString = "Here is my string";
    }

    public string MyString
    {
        get;
        set;

    }
}


<Button Content="Test Button" 
     Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}">
  <Button.ContextMenu>
    <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, 
          RelativeSource={RelativeSource Self}}" >
      <MenuItem Header="{Binding MyString}"/>
    </ContextMenu>
  </Button.ContextMenu>   
</Button>

重要な部分はボタンのタグです (ただし、ボタンの DataContext を簡単に設定できます)。親ウィンドウへの参照を格納します。ContextMenu は、PlacementTarget プロパティを介してこれにアクセスできます。その後、このコンテキストをメニュー項目に渡すことができます。

これが世界で最もエレガントなソリューションではないことは認めます。ただし、コードビハインドでの設定に勝ります。誰かがこれを行うためのさらに良い方法を持っているなら、私はそれを聞きたいです.

于 2010-09-08T14:23:37.313 に答える
-1

ビジュアル ツリーにないためContextMenu、バインディングは機能しません。簡単な解決策はプロキシ パターンを使用することです。 から継承しDependencyObjectDependencyPropertyを保持するラッパー クラスを作成できDataContextますWindow。次に、XAML でプロキシのリソースを取得し、最後にMenuItemプロキシを介してコマンドを目的のコマンドにバインドできます。物体。
サンプル プロキシ:

Public class ProxyClass : DependencyObject
{
    Public object Data {get; set;}
   public static readonly DependencyProperty DataProperty = DependencyProperty.Register("DataProperty", typeof(object), typeof(ProxyClass), new FrameworkPropertyMetadata(null));

}

XAML での使用方法:

<Window DataContext="{Binding MyViewModel}">
...
<Window.Resources>
    <ProxyClass Data={Binding} x:Key="BindingProxy"/>

</Window.Resources>
...  
<MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/>
...
</Window>

何が起こっている?
Dataプロパティ ofはofProxyClassにバインドされ、リソース内にすべてのコマンドとプロパティがあります。 このアプローチのもう 1 つの利点は、移植性と、複数のビューやプロジェクトでの再利用です。DataContextWindowViewModelProxyClass

于 2017-01-06T12:40:56.723 に答える
-3

次のようにすればよいと思います。

{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
于 2010-09-08T14:24:33.573 に答える