在ContextMenu中访问ViewModel / DataConext

本文关键字:DataConext ViewModel 访问 ContextMenu | 更新日期: 2023-09-27 18:03:35

如何在ContextMenu中获得UserControl的原始DataContext。

在下面的代码中,您可以看到DataTemplate中有一个Button,它正确地绑定了。但是,当尝试绑定上下文菜单的数据源时,我收到以下错误:

System.Windows。数据错误:4:找不到绑定引用'RelativeSource FindAncestor, AncestorType='System.Windows.Controls '的源。TreeView",AncestorLevel ="1"。BindingExpression:路径= DataContext;DataItem =零;目标元素是'ContextMenu' (Name= ");目标属性为"DataContext"(类型为"Object")

我需要做什么来允许ContextMenu绑定到ViewModel?

===============================================================================

ViewModel在代码后面被分配给视图的数据上下文:

视图:

<TreeView ItemsSource="{Binding Clients}"
          cmd:TreeViewSelect.Command="{Binding SelectionChangedCommand}"
          cmd:TreeViewSelect.CommandParameter="{Binding RelativeSource={RelativeSource Self},Path=SelectedItem}">
    <TreeView.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Name}">
                    <TextBlock.ContextMenu>
                        <ContextMenu DataContext="{Binding DataContext, 
                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}}">
                            <MenuItem Header="{Binding TestString}" />
                        </ContextMenu>
                    </TextBlock.ContextMenu>
                </TextBlock>
                <Button  DataContext="{Binding DataContext, 
                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeView}}}"
                         Content="{Binding TestString}" Command="{Binding EditSelectedClientCommand}" />
             </StackPanel>
        </DataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

ViewModel:

public class ClientListViewModel : ViewModelBase
{
    public String TestString { 
        get {
            return "TESTING";  
        }
    }
    private ClientList _clients = null;
    private readonly IClientService _clientService = null;
    private readonly IEventAggregator _eventAggregator = null;
    private Client _selectedClient = null;
    private ICommand _selectionChangedCommand = null;
    private ICommand _editSelectedClientCommand = null;
    ....
}

在ContextMenu中访问ViewModel / DataConext

ContextMenus没有出现在导致relativessource绑定失败的可视化树中,但是您仍然可以以某种方式获得DataContext。您可以这样做,例如:

<TextBlock Text="{Binding Name}"
           Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=TreeView}}">
    <TextBlock.ContextMenu>
        <ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
            <MenuItem Header="{Binding TestString}" />
            <!-- ... --->

PlacementTarget为TextBlock, DataContext通过Tag隧道。只有一种方法可以做到这一点(至少我希望它能起作用),我也看到一些库以不同的方式弥合了这个差距,但我不记得它们的起源…