这很棘手,因为 ToolTip 不是 VisualTree 的一部分。在这里,您可以看到针对 ContextMenus 相同问题的一个很酷的解决方案。与工具提示相同的方式。
更新
遗憾的是,链接已经消失,我再也找不到引用的文章了。
据我记得,引用的博客已经展示了如何绑定到另一个 VisualTree 的 DataContext,这在从 ToolTip、ContextMenu 或 Popup 绑定时通常是必需的。
一个很好的方法是在 PlacementTarget 的标记属性中提供所需的实例(例如 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 属性访问它。然后,您可以通过菜单项将此上下文向下传递。
我承认这不是世界上最优雅的解决方案。但是,它胜过在后面的代码中设置东西。如果有人有更好的方法来做到这一点,我很想听听。