天天看點

WPF Command綁定并傳參(以DataGrid示例)

一、問題場景:

  使用WPF的DataGrid來展示表格資料,想要批量删除或者導出資料行時,由于SelectedItems屬性不支援MVVM的方式綁定(該屬性是隻讀屬性),是以可以通過指令參數的方式将該屬性值傳給指令,即利用CommandParameter将SelectedItems傳遞給删除或導出指令。

二、使用方式:

1.xaml部分

<DataGrid x:Name="dtgResult" ItemsSource="{Binding ResultInfo}" CanUserSortColumns="True" Height="205" Width="866" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="患者ID" Binding="{Binding PatientId}" MinWidth="46" IsReadOnly="True"/>
        <DataGridTextColumn Header="姓名" Binding="{Binding PatientName}" MinWidth="46" IsReadOnly="True"/>
        <DataGridTextColumn Header="性别" Binding="{Binding PatientGender}" MinWidth="46" IsReadOnly="True"/>
    </DataGrid.Columns>
</DataGrid>      
<Button x:Name="btnResultDel" Content="删除" Command="{Binding ResultDeleteCommand}" CommandParameter="{Binding SelectedItems,ElementName=dtgResult}"/>      

2.C#部分

private RelayCommand _deleteCommand;
public ICommand ResultDeleteCommand
{
  get
  {
    if (_deleteCommand == null)
    {
      _deleteCommand = new RelayCommand(param =>On_Delete_Command_Excuted(param));
    }
  return _deleteCommand;
  }
}
private void On_Delete_Command_Excuted(Object param)
{

}      

每次觸發ResultDeleteCommand,都會把控件dtgResult的SelectedItems屬性值作為參數param傳遞給On_Delete_Command_Excuted方法。

三、Tip

1.如何把Object類型的參數轉成List<T>呢? (其中T是DataGrid中每條資料的類型)

System.Collections.IList items = (System.Collections.IList)param;
var collection = items.Cast<T>();
var selectedItems = collection.ToList();      

其中selectedItems就是使用者在DataGrid界面選中的多條資料行。

2.RelayCommand

/// <summary>
/// A command whose sole purpose is to relay its functionality to other objects by invoking delegates. The default return value for the CanExecute method is 'true'.
/// </summary>
public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;        

    /// <summary>
    /// Creates a new command that can always execute.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    public RelayCommand(Action<object> execute): this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
         if (execute == null)
            throw new ArgumentNullException("execute");

         _execute = execute;
         _canExecute = canExecute;           
    }
        
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

}