【问题标题】:Context menu binding never gets executed上下文菜单绑定永远不会被执行
【发布时间】:2016-11-08 23:25:44
【问题描述】:

我的视图中有 ListView 控件,它有自己的视图模型 A。我制作了一个单独的 UserControl 用作 ListViewItem,因为它的样式占用了大量空间。在这个 ListViewItem 中,我有一个按钮,它绑定到 viewmodel A 并且工作正常。

由于上下文菜单有它自己的可视化树并且不能通过祖先绑定,我使用binding proxy 来解决这个问题。我对其进行了一些调整,使其适用于我的特定情况,因为如果它只使用 {Binding} 它将绑定到项目的模型,而不是列表视图的视图模型。

<helpers:BindingProxy x:Key="proxy" Data="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}"/>

为了检查绑定是否正确,我使用转换器作为一种方法,只是为了有一个断点来检查源代码。一切都很好,我的视图模型就在那里。

现在,当我尝试在上下文菜单中绑定到 this 时

<UserControl.ContextMenu>
    <ContextMenu>
        <MenuItem Header="Open"
                  Command="{Binding DataContext.OpenChatCommand, Source={StaticResource proxy}, Converter={StaticResource DataBindingDebugConverter}}"
                  CommandParameter="{Binding}"/>
   </ContextMenu>
</UserControl.ContextMenu>

该命令永远不会被调用。我添加了转换器以查看是否有问题,但事实证明,我从来没有使用过我的转换器,这反过来意味着这段代码永远不会被执行。

欢迎任何对为什么会发生这种情况以及如何解决此问题有任何想法的人。

我认为是编译器出现故障

【问题讨论】:

    标签: c# wpf mvvm contextmenu


    【解决方案1】:

    我刚刚对您提到的那个“绑定代理”做了一个简短的阅读,但据我所知,DataGridTextColumn 与其DataGrid 位于同一可视树中,只是它的DataContext 绑定到它的数据。

    对于ContextMenu,情况完全不同。这个真的有一个与其父级分开的树。在资源中使用代理对象是没有意义的,因为它来自不同的可视化树。当您使用StaticResource 时,WPF 将在这些元素的Resource 属性(即ResourceDictionary)内逐级向上搜索其可视化树。

    一种方法是将该代理设置为单例,并使用Source={x:Static helpers:BindingProxy.Instance}。当然使用这个意味着你的代理只能被单个 View 使用,否则会发生意想不到的事情。

    另一种方法是利用ContextMenuPlacementTarget属性。

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

    这是首选方式,但您需要确保父级的 DataContext 确实是您需要的 VM。

    编辑

    没有超级优雅的方式来实现 MVVM 方式。最好的方法可能是通过使用Tag 属性。

    <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag,
                 RelativeSource={RelativeSource Self}}">
    

    ListView 控件:

    <MyControl:MyListViewItem .... Tag="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType={x:Type MyControl:MyListViewView}}}"}" ...>
    

    【讨论】:

    • 现在我可以绑定ListViewItem的模型了,但是还是不能绑定ListView的DataContext。仍然不是我需要的。
    • @Dainius 更新。
    • 我们越来越近了!当我单击菜单项上的命令时,出现此异常:"System.InvalidCastException' occurred in GalaSoft.MvvmLight.Platform.dll Unable to cast object of type 'MainViewModel' to type 'MatchModel'." 我使用转换器查看 Command 上的值是我的 MenuItem 获得的值,它是 RelayCommand,它是非公共成员 _execute、属性 Target 和 ActionTarget,放置我正在寻找的虚拟机。
    • @Dainius 好的,我不是 MVVM Light 用户,所以这绝对超出了我的正常理解范围。 MatchModel 是什么,它是如何进入内部的?
    • MatchModel 是我的 ListViewItem 绑定到的实际模型。它包含在我的 MainViewModel 中。我的 ListView 的 ItemSource 是 List。到目前为止,我已经解决了我的问题,只需在 ListView 中添加 ContextMenu,而不是在 ListViewItem 中,它现在是一些意大利面条代码,但至少它可以工作。如果你当时不知道如何解决这个没关系,你仍然帮助了我,我现在已经了解了标签!
    猜你喜欢
    • 2019-12-07
    • 2021-08-19
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 1970-01-01
    相关资源
    最近更新 更多