如何在执行命令之前转换命令参数?

How to convert command parameter just before command is executed?

我的视图中有一个 DataGrid,DataGrid 有带按钮的单元格,这些按钮已分配了命令。现在我希望将当前行对象(位于 DataGrid.CurrentItem 中)传递给命令执行逻辑。

我最初的想法是将 CommandParameter 与值转换器一起使用,其中转换器会将 DataGrid 作为参数并将所需的信息从 DataGrid 提取到我自己的 class - 这样我就可以避免从我的视图中引用 DataGrid模型。

问题是,在显示网格时执行 CommandParameter binding/value 转换,这意味着还没有选择的项目。

我能否以某种方式避免将 DataGrid 引用引入我的命令执行逻辑中,例如推迟 CommandParameter 解析直到命令执行或类似的事情?

更新:我需要 CurrentItem 和 CurrentColumn,我已经意识到,CurrentItem 可能可以通过 SelectedItem 的绑定访问,所以为了避免收到建议使用 SelectedItem 的答案 属性。

  • 你的命令参数应该是 CommandParameter="{Binding}" 这样参数将是单击按钮的行 DataContext,这是您的模型的一个实例。
  • 将您的参数投射到您的 commadns 中的模型 Execute 方法。
  • 比如说你想阻止命令的执行 如果 SelectedItem 为 null 或者必须选择 Item,则 您所需要的只是 return 来自 CanExecute 方法的布尔值 随心所欲。

所以我最初的想法很接近。

当我将 CommandParameter 绑定到 DataGrid 时,问题是,当绑定解析时,DataGrid 还不知道 CurrentColumn、CurrentCell 或 CurrentItem 是什么,所以它解析为空值。

所以我更改了绑定以改为绑定到 DataGridCell - 问题解决了 - Cell 能够在绑定解析时间告诉它它属于的列和项目,所以当命令被触发时,它具有所有正确的数据已经.

样式看起来像这样:

<Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}},    
                          Path=DataContext[RowActionFeature].RowActionCommand}"                                                                                                      
        CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridCell}}, 
                                   Converter={StaticResource DataGridCellToRowActionParametersConverter}}">
...
</Button>

转换器是这样的:

public class DataGridCellToRowActionParametersConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var dataGridCell = value as DataGridCell;

        if (dataGridCell == null)
        {
            return null;
        }

        var dataRowView = dataGridCell.DataContext as DataRowView;
        var columnIndex = dataGridCell.Column.DisplayIndex;

        return new RowActionParameters
               {
                   Item = dataGridCell.DataContext,
                   ColumnPropertyName = dataGridCell.Column.SafeAccess(x => x.SortMemberPath),
                   DataRowView = dataRowView,                      
                   ColumnIndex = columnIndex
               };
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}