Wpf 工具提示或上下文菜单中的相对资源绑定

Wpf 工具提示或上下文菜单中的相对资源绑定,wpf,xaml,binding,relativesource,Wpf,Xaml,Binding,Relativesource,我做错了什么 <GridViewColumn> <GridViewColumn.CellTemplate> <DataTemplate> <Button> <Button.ToolTip> <TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource Ances

我做错了什么

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

这只是一个简化的示例,无论如何都不起作用:) 实际上,我需要从窗口的DataContext范围内的另一个属性中获取一个值


请帮帮我。

这很棘手,因为工具提示不是VisualTree的一部分。对于同一个问题,您可以通过ContextMenus看到一个很酷的解决方案。与工具提示的方式相同

更新
遗憾的是,链接不见了,我再也找不到引用的文章了。
就我所记得的,引用的博客展示了如何绑定到另一个VisualTree的DataContext,这在从工具提示、上下文菜单或弹出窗口绑定时经常是必需的

一个很好的方法是在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中的上下文菜单不存在于 就页面/窗口/控件本身而言,数据绑定可能有点棘手。 我在网上到处寻找这个,而且最 常见的答案似乎是“只需在代码背后做”。错了!我 没有回到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>
公共部分类窗口1:窗口
{
公共窗口1()
{
MyString=“这是我的字符串”;
}
公共字符串MyString
{
得到;
设置
}
}
重要的部分是按钮上的标签(尽管您可以 轻松设置按钮的DataContext)。这将存储对的引用 父窗口。ContextMenu能够访问此 通过它的PlacementTarget属性。然后可以传递此上下文 浏览菜单项

我承认这不是世界上最优雅的解决方案。 然而,它胜过在代码背后设置东西。如果有人有 更好的方法我很想听听


我认为应该这样做:

{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"

因为
ContextMenu
不在可视化树中,绑定将无法工作。 一个简单的解决方案是使用代理模式,您可以创建一个从
DependencyObject
继承的包装类,并具有
DependencyProperty
,该属性将保留
窗口的
DataContext
,然后,您可以在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));

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

</Window.Resources>
...  
<MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/>
...
</Window>
如何在XAML中使用:

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

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

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

...
...  
...
发生了什么事?
ProxyClass
Data
属性将绑定到
Window
DataContext
,然后它在
ProxyClass
资源中包含您的
ViewModel
的所有组件和属性。
这种方法的另一个好处是可移植性,并可在多个视图和项目中重复使用。

参见下文:
PlacementTarget是拥有ContextMenu(例如:DataGrid)的控件。不需要“标记”属性

IsEnabled绑定到DataGrid的“myProperty”值

我测试了这个,它是有效的。在绑定方面也有类似的问题

<ContextMenu
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"
IsEnabled="{Binding myProperty}"  
>


这不起作用,因为工具提示中没有主VisualTree。查看我的答案。耶,对不起,我甚至没有注意到它在工具提示中。@Bill我再也找不到该链接,但我已尝试解释如何解决该问题。该解决方案非常有用,而且比以前让我无法使用上下文菜单和工具提示的“namescope hack”解决方案简单得多。这是令人厌恶的简单和完美的作品。@ChrisValentine请随意搅乱我的编辑;我只是想确保原始解决方案记录在这里。这种方法只能在同一个窗口xaml上使用code@TuanTran“仅在同一窗口上使用xaml代码”的确切含义是什么?不能将
部分拆分为单独的资源文件