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代码”的确切含义是什么?不能将…
部分拆分为单独的资源文件