将数据网格上下文菜单的命令参数绑定到所选行的列值

时间:2019-06-03 08:57:29

标签: wpf data-binding datagrid contextmenu

我有一个绑定到ObservableCollection的数据网格。数据网格具有上下文菜单。单击上下文菜单项时,将触发绑定的命令,但是我想传递绑定到所选数据网格行的ID的命令参数。该命令被触发,但参数为空。

下面是我尝试过的代码。

 <DataGrid Name="users" ItemsSource="{Binding UsersModel}" CanUserAddRows="False" IsReadOnly="True" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Id}" Header="User Id" Width="auto"/>
        <DataGridTextColumn Binding="{Binding Name}" Width="*" Header="User Name"/>
        <DataGridTextColumn Binding="{Binding IsRegistered, Converter={StaticResource BoolToYesNoConverter}}" Width="auto" Header="Registered" />
        <DataGridTextColumn Binding="{Binding RegisteredOn}" Width="*" Header="Registration Date"/>
        </DataGrid.Columns>
        <DataGrid.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Modify" Command="{Binding Modify}" CommandParameter="{Binding Id}"/>
                <MenuItem Header="Delete" Command="{Binding Delete}" CommandParameter="{Binding Id}" />
            </ContextMenu>
        </DataGrid.ContextMenu>
</DataGrid>

我希望将所选行的ID作为命令参数传递。

3 个答案:

答案 0 :(得分:1)

我将在视图模型上创建一个SelectedRow属性,以将所选行存储在网格中,然后将上下文菜单项命令绑定到该视图模型上引用SelectedRow属性的命令。 我必须在上下文菜单相对源上使用PlacementTarget。

//在视图模型中

public DelegateCommand ModifyCommand { get; }

ModifyCommand = new DelegateCommand(() => { var Id = SelectedRow.Id; //... });

private UsersModel _selectedRow;
public UsersModel SelectedRow
{
    get => _selectedRow;
    set
    {
        _selectedRow = value;
        OnPropertyChanged(nameof(SelectedRow));
    }
}

//在视图中

DataGrid Name="users" ItemsSource="{Binding Items}" CanUserAddRows="False" IsReadOnly="True" AutoGenerateColumns="False"
    SelectedItem="{Binding SelectedRow, Mode=TwoWay}" >

// and on context menu
<MenuItem Header="Modify" Command="{Binding PlacementTarget.DataContext.ModifyCommand, 
    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" />

答案 1 :(得分:0)

向视图模型添加SelectedId属性(定义了UsersModel和command属性),然后将DataGrid的SelectedValue属性绑定到该属性。

然后将SelectedId用于CommandParameter绑定。当然,请确保SelectedId触发PropertyChanged事件。

<DataGrid ... SelectedValuePath="Id" SelectedValue="{Binding SelectedId}">
    ...
    <DataGrid.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Modify"
                      Command="{Binding Modify}"
                      CommandParameter="{Binding SelectedId}"/>
            <MenuItem Header="Delete"
                      Command="{Binding Delete}"
                      CommandParameter="{Binding SelectedId}" />
        </ContextMenu>
    </DataGrid.ContextMenu>
</DataGrid>

答案 2 :(得分:0)

我假设您的ViewModel类实现了INotifyPropertyChanged接口,并且假定您实现了一种用于触发属性更改的方法,在这里我将此方法称为RaisePropertyChanged。毕竟, 在您的viewModel类中定义一个私有字段selectedUsers和一个名称为SelectedUsers的属性:

private UsersModel selectedUsers;

public UsersModel SelectedUsers
    {
        get => _selectedFields;

        set
        {
            _selectedFields = value;
            Modify.RaiseCanExecuteChanged();
            Delete.RaiseCanExecuteChanged();
        }
    }

添加之后,必须将SelectionChanged事件添加到Grid,然后在seletedUser的代码隐藏设置值中如下所示:

private void usersGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        usersViewModel.SelectedUsers = usersGrid.SelectedItem as UsersModel;
    }

并将selectedItem中的DataGrid绑定到selectedUser

<DataGrid Name="users" ItemsSource="{Binding Items}" CanUserAddRows="False" 
IsReadOnly="True" AutoGenerateColumns="False"
SelectedItem="{Binding SelectedUser}" >

完成这些工作时,可以在viewModel中访问selectedUser