WPF:将 ContextMenu 绑定到 MVVM 命令 [英] WPF: Binding a ContextMenu to an MVVM Command

查看:55
本文介绍了WPF:将 ContextMenu 绑定到 MVVM 命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 Window,其属性返回一个 Command(实际上,它是一个 UserControl,在 ViewModel 类中带有一个 Command,但让我们尽可能简单地重现问题).

Let's say I have a Window with a property returning a Command (in fact, it's a UserControl with a Command in a ViewModel class, but let's keep things as simple as possible to reproduce the problem).

以下工作:

<Window x:Class="Window1" ... x:Name="myWindow">
    <Menu>
        <MenuItem Command="{Binding MyCommand, ElementName=myWindow}" Header="Test" />
    </Menu>
</Window>

但以下方法不起作用.

<Window x:Class="Window1" ... x:Name="myWindow">
    <Grid>
        <Grid.ContextMenu>
            <ContextMenu>
                <MenuItem Command="{Binding MyCommand, ElementName=myWindow}" Header="Test" />
            </ContextMenu>            
        </Grid.ContextMenu>
    </Grid>
</Window>

我得到的错误信息是

System.Windows.Data 错误:4:找不到引用ElementName=myWindow"的绑定源.BindingExpression:Path=MyCommand;数据项=空;目标元素是 'MenuItem' (Name='');目标属性是'Command'(类型'ICommand')

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=myWindow'. BindingExpression:Path=MyCommand; DataItem=null; target element is 'MenuItem' (Name=''); target property is 'Command' (type 'ICommand')

为什么?我该如何解决这个问题?使用 DataContext 不是一个选项,因为这个问题发生在可视化树的下方,其中 DataContext 已经包含正在显示的实际数据.我已经尝试使用 {RelativeSource FindAncestor, ...} 代替,但是会产生类似的错误消息.

Why? And how do I fix this? Using the DataContext is not an option, since this problem occurs way down the visual tree where the DataContext already contains the actual data being displayed. I already tried using {RelativeSource FindAncestor, ...} instead, but that yields a similar error message.

推荐答案

问题是 ContextMenu 它不在可视化树中,所以你基本上要告诉 Context menu 使用哪个数据上下文.

The problem is that the ContextMenu it not in the visual tree, so you basically have to tell the Context menu about which data context to use.

查看 这篇博文 有一个非常好的 Thomas Levesque 解决方案.

Check out this blogpost with a very nice solution of Thomas Levesque.

他创建了一个继承 Freezable 的类 Proxy 并声明了一个 Data 依赖属性.

He creates a class Proxy that inherits Freezable and declares a Data dependency property.

public class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

然后可以在 XAML 中声明它(在可视化树中已知正确 DataContext 的位置):

Then it can be declared in the XAML (on a place in the visual tree where the correct DataContext is known):

<Grid.Resources>
    <local:BindingProxy x:Key="Proxy" Data="{Binding}" />
</Grid.Resources>

并在可视化树外的上下文菜单中使用:

And used in the context menu outside the visual tree:

<ContextMenu>
    <MenuItem Header="Test" Command="{Binding Source={StaticResource Proxy}, Path=Data.MyCommand}"/>
</ContextMenu>

这篇关于WPF:将 ContextMenu 绑定到 MVVM 命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆