我的视图中有ListView控件和它自己的viewmodel A.我已经将一个单独的UserControl用作ListViewItem,因为它的样式占用了大量空间。在这个ListViewItem中,我有一个按钮,绑定到viewmodel A,它工作正常。
由于上下文菜单具有自己的可视树,无法通过祖先进行绑定,因此我使用了binding proxy来解决此问题。我已经调整了一点,所以它适用于我的特定情况,因为如果它只使用{Binding}它将绑定到item的模型,而不是listview的viewmodel。
<helpers:BindingProxy x:Key="proxy" Data="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}}"/>
要检查绑定是否正确,我已经使用转换器作为断点来检查源的方法。一切都很好,我正在那里获得我的视图模型。
现在,当我尝试在我的上下文菜单中绑定到它时
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Open"
Command="{Binding DataContext.OpenChatCommand, Source={StaticResource proxy}, Converter={StaticResource DataBindingDebugConverter}}"
CommandParameter="{Binding}"/>
</ContextMenu>
</UserControl.ContextMenu>
该命令永远不会被调用。我添加了转换器以查看是否有问题,但事实证明,我从未接触到我的转换器,这反过来意味着这个代码永远不会被执行。
任何有任何想法的人都会发生这种情况以及如何解决这个问题。
我认为编译器出现故障
答案 0 :(得分:2)
我刚刚对你提到的那个“绑定代理”进行了简短的阅读,但据我所知,DataGridTextColumn
与DataGrid
在同一个Visual Tree中,只是它的{{1}绑定到它的数据。
对于DataContext
,它完全不同。这个实际上与其父级有一个单独的树。在资源中使用代理对象没有意义,因为它来自不同的可视树。当您使用ContextMenu
时,WPF将在这些元素'StaticResource
属性(Resource
)内逐级搜索其可视树。
一种方法是将该代理转换为单例,并使用ResourceDictionary
。当然,使用这意味着您的代理只能由单个View使用,否则会发生意外情况。
另一种方法是使用Source={x:Static helpers:BindingProxy.Instance}
的{{3}}属性。
ContextMenu
这是首选方法,但您需要确保父{æ}}真正是您需要的虚拟机。
MVVM方式没有超级优雅的方式。最好的方法可能是使用PlacementTarget
属性。
<ContextMenu DataContext="{Binding Path=PlacementTarget.DataContext,
RelativeSource={RelativeSource Self}}">
ListView控件:
DataContext