MVVM 如何将命令绑定到 ContextMenu

MVVM How to bind command to ContextMenu

我对使用 relativeSource 和 ancestorLevel 感到很困惑。 相对源用于从另一个元素获取源。但要成功做到这一点,您必须计算该元素处于什么级别。 (如何调试?) WPF中最容易混淆的地方

在我的例子中,我有上下文菜单,我想绑定数据源然后命令。绑定必须如何才能在我的虚拟机中获取命令?谢谢

 <Page.DataContext>
    <PDB:UsersViewModel x:Name="vm"/>
</Page.DataContext>


<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <!--Page Header info content-->
    <Grid Grid.Row="0">
        <TextBlock Text="{Binding SelectedUser.Name}"/>
        <TextBlock Text="{Binding ElementName=myGrd, Path=CurrentColumn.DisplayIndex}"/>
    </Grid>
    <!--Datagrid content-->
    <DataGrid x:Name="myGrd" 
              SelectionMode="Single"    
              SelectionUnit="Cell"
              CurrentItem="{Binding SelectedUser, Mode=TwoWay}"
              CurrentColumn="{Binding CurrentColumn, Mode=TwoWay}"
              IsReadOnly="True"
              Grid.Row="1" 
              ItemsSource="{Binding FilteredUserList}" 
              AutoGenerateColumns="True"             
              CanUserAddRows="False"
              >
        <DataGrid.Resources>
            <ContextMenu x:Key="ContextMenu">
                <ContextMenu.Items>
                    <MenuItem Header="{Binding 
                        RelativeSource={RelativeSource  
                        FindAncestor,
                        AncestorType={x:Type Page}, 
                        AncestorLevel=4}, Path=vm}" />
                </ContextMenu.Items>
            </ContextMenu>
        </DataGrid.Resources>

        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Setter Property="ContextMenu" Value="{StaticResource ContextMenu}"/>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>
</Grid>

您不能在 ContextMenu 中使用 RelativeSource,因为菜单不是可视化树的一部分。然而,这可以通过使用绑定源和 x:Reference.

来避免。

我假设您的 ViewModel 看起来像这样

public class UserViewModel
{
    public string Header { get; set; }
    public ICommand MyCommand { get; }
    ... more code
}

现在让我们绑定 VM 的 Header 和 MyCommand 属性

<ContextMenu x:Key="ContextMenu">
    <ContextMenu.Items>
        <MenuItem Header="{Binding Header, Source={x:Reference vm}}"
                  Command="{Binding MyCommand, Source={x:Reference vm}}"/>
    </ContextMenu.Items>
</ContextMenu>

重要的部分是将 ViewModel 放在可视化树中的某个位置并设置它 x:Name,就像您在示例中所做的那样

<Page.DataContext>
    <PDB:UsersViewModel x:Name="vm"/>
</Page.DataContext>

如果你还想进一步了解RelativeSource,这个question好像和你有同样的问题。基本上,绑定的路径必须是 DataContext.MyViewModelProperty,绑定的 RelativeSource 必须是 DataContext 设置为 ViewModel 的元素。