繁体   English   中英

将CommandParameter从MenuItem绑定到父DataGrid

[英]Bind CommandParameter from MenuItem to Parent DataGrid

如何将命令参数从MenuItem绑定到父Grid DataContext?

我有一个带有ContextMenu的DataGrid,它将菜单项绑定到ViewModel命令,但是command参数始终为null。

我在DataGrid中使用Tag参数来访​​问DataContext并使用所需的命令,但是可以弄清楚它从每一行中获取绑定数据以用作命令参数。

我在这里已经研究了很多答案,但是找不到任何可行的方法,因此调用了ViewModel中的command参数,并且command参数始终为null。

C#

public class People
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class PeopleWindowViewModel
{
    public List<People> Peoples { get; set; }

    public PeopleWindowViewModel()
    {
        // populate Peoples list...
    }

    public ICommand RemoveCommand
    {
        get
        {
            return RelayCommand.Create((m) =>
            {
                // m always null
            });
        }
    }
}

public class PeoplePage : Page
{
    public PeoplePage()
    {
        InitializeComponent();

        DataContext = new PeopleWindowViewModel();
    }
}

XAML:

  <DataGrid
      Margin="0 8 0 8"
      d:DataContext="{d:DesignInstance local:People}"
      IsReadOnly="True"
      ItemsSource="{Binding Peoples}"
      Tag="{Binding DataContext,
                      RelativeSource={RelativeSource AncestorType={x:Type Page}}}">
    <DataGrid.Columns>
      <DataGridTextColumn
          Binding="{Binding Id}"
          Header="Id" />
      <DataGridTextColumn
          Binding="{Binding Name}"
          Header="Name" />
    </DataGrid.Columns>

    <DataGrid.ContextMenu>
      <ContextMenu
          Tag="{Binding Path=PlacementTarget.Tag,
                              RelativeSource={RelativeSource Self}}">
        <MenuItem
            Command="{Binding PlacementTarget.Tag.RemoveCommand,
                                      RelativeSource={RelativeSource Mode=FindAncestor,
                                                                     AncestorType=ContextMenu}}"
            CommandParameter="{Binding Path=Id,
                                               RelativeSource={RelativeSource Mode=FindAncestor,
                                                                              AncestorType=DataGrid}}"
            Header="Remover" />
      </ContextMenu>
    </DataGrid.ContextMenu>
  </DataGrid>
</Page>

我找到了解决方案,但是不确定是否有更好的解决方案。 无论如何,您可以这样做:

<DataGrid ItemsSource="{Binding Peoples}">
    <DataGrid.Resources>
        <ContextMenu x:Key="ctx_menu">
            <ContextMenu.Resources>
                <Style TargetType="{x:Type MenuItem}">
                    <Setter Property="DataContext" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                </Style>
            </ContextMenu.Resources>
            <MenuItem Command="{Binding DataContext.RemoveCommand}"
                      CommandParameter="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
                      Header="Remove" />
        </ContextMenu>
    </DataGrid.Resources>

    <DataGrid.ItemContainerStyle>
        <Style TargetType="{x:Type DataGridRow}">
            <Setter Property="ContextMenu" Value="{StaticResource ctx_menu}" />
        </Style>
    </DataGrid.ItemContainerStyle>

</DataGrid>

编辑:这给您整个人对象作为CommandParameter。 如果只需要Id,只需将CommandParameter更改为:

CommandParameter="{Binding PlacementTarget.DataContext.Id, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"

如果必须将ContextMenu保留在UI-LIB的DataGrid中,则必须知道,在您的情况下,这通常是错误的做法。 上下文菜单应该转到您需要...上下文的位置,这就是您的行。 但是无论如何,还是有一些丑陋的“解决方案”。 这是一个:

在您的Xaml中,只需绑定Command并忽略CommandParameter。

<DataGrid ItemsSource="{Binding Peoples}">
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Command="{Binding RemoveCommand}"
                      Header="Remove" />
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>

在您的ICommand方法中,您可以执行以下操作:

private void Remove(object obj)
{
    obj = Mouse.DirectlyOver as FrameworkElement;
    if (obj != null)
        obj = ((FrameworkElement)obj).DataContext;

    // obj should be one People here
}

这在大多数情况下都应该起作用,但是实际上,通常您会尽量避免这种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM