我在这里做错了什么?:
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button>
<Button.ToolTip>
<TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" />
这只是一个简单的例子,无论如何都不起作用:) 实际上我需要从Window的DataContext范围内的另一个属性中获取一个值。
请帮帮我。
答案 0 :(得分:69)
这很棘手,因为ToolTip不是VisualTree的一部分。 Here您看到了与ContextMenus相同问题的一个很酷的解决方案。您可以使用与工具提示相同的方式。
<强>更新强>
可悲的是,链接已经消失了,我还没有找到引用的文章。
据我所知,引用的博客已经展示了如何绑定到另一个VisualTree的DataContext,这在从ToolTip,ContextMenu或Popup进行绑定时经常是必需的。
一种很好的方法是在PlacementTarget的Tag-property中提供所需的实例(例如ViewModel)。以下示例用于访问ViewModel的Command实例:
<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和found the original blog entry。这是博客中的逐字:
因为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属性。然后,您可以传递此上下文 浏览菜单项。
我承认这不是世界上最优雅的解决方案。 但是,它在背后的代码中胜过设置。如果有人有 更好的方式,我很乐意听到它。
答案 1 :(得分:3)
以下:
PlacementTarget是拥有ContextMenu的控件(例如:DataGrid)。不需要&#34;标签&#34;属性。
IsEnabled绑定到DataGrid&#34; myProperty&#34;值。
我测试了这个并且它有效。与绑定有类似的问题。
<ContextMenu
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"
IsEnabled="{Binding myProperty}"
>
答案 2 :(得分:0)
由于ContextMenu
不在可视树中,因此绑定不起作用。
一个简单的解决方案是使用代理模式,您可以创建一个继承自DependencyObject
的包装类,并且DependencyProperty
将保留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
ProxyClass
的{{1}}属性将绑定到DataContext
的{{1}},然后它Window
中包含ViewModel
的所有comamnds和属性资源。
这种方法的另一个好处是可移植性和在多个视图和项目中重用。
答案 3 :(得分:-2)
我认为应该这样做:
{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"