(可选)将类型T的参数传递给Action

时间:2019-01-08 22:42:01

标签: c# wpf mvvm parameters action

我有一个名为RelayCommand的类,它继承了这样定义的ICommand接口:

/// <summary>
/// Base command that executes an <see cref="Action"/>.
/// </summary>
public class RelayCommand : ICommand
{
    #region Members

    // The Action to run.
    private Action mAction;

    #endregion

    #region Events

    /// <summary>
    /// Event fired when the value of <see cref="CanExecute(object)"/> changes.
    /// </summary>
    public event EventHandler CanExecuteChanged = (sender, e) => { };

    #endregion

    #region Constructor

    /// <summary>
    /// Default <see cref="RelayCommand"/> constructor.
    /// </summary>
    public RelayCommand(Action action)
    {
        mAction = action;
    }

    #endregion

    #region Command Methods

    /// <summary>
    /// A <see cref="RelayCommand"/> can always be executed.
    /// </summary>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public bool CanExecute(object parameter)
    {
        return true;

    }

    /// <summary>
    /// Executes the <see cref="Action"/> of the command.
    /// </summary>
    /// <param name="parameter"></param>
    public void Execute(object parameter)
    {
        mAction();
    }

    #endregion 
}

我使用此类在整个应用程序中执行命令,有时需要执行Action并在XAML中传递参数。问题是该参数传递是可选的,但是我找不到适合我正在执行的解决方案。例如,我有这三个命令基本上可以完成相同的操作。我通过UI将PriorityLevelenum值)设置为对象,然后根据单击哪个控件,执行以下三种方法之一:

    /// <summary>
    /// What to do when the priority of the task is set to <see cref="PriorityLevel.Low"/>
    /// </summary>
    private void OnSetLowPriorityCommand()
    {
        Priority = PriorityLevel.Low;
        PriorityGridWidth = 10;
        PriorityFlagOpacity = 0;
        mIsPriorityChanged = true;
    }

    /// <summary>
    /// What to do when the priority of the task is set to <see cref="PriorityLevel.Medium"/>
    /// </summary>
    private void OnSetMediumPriorityCommand()
    {
        Priority = PriorityLevel.Medium;
        PriorityGridWidth = 10;
        PriorityFlagOpacity = 0;
        mIsPriorityChanged = true;
    }

    /// <summary>
    /// What to do when the priority of the task is set to <see cref="PriorityLevel.High"/>
    /// </summary>
    private void OnSetHighPriorityCommand()
    {
        Priority = PriorityLevel.High;
        PriorityGridWidth = 10;
        PriorityFlagOpacity = 0;
        mIsPriorityChanged = true;
    }

如您所见,除了方法的第一行之外,其余的都是相同的,但是我认为,如果我只保留一个称为SetPriorityCommand的方法,那会更好。 switch或其他任何值都可以设置正确的PriorityLevel值。然后,我像这样消耗Action

    SetLowPriorityCommand = new RelayCommand(OnSetLowPriorityCommand);

无论如何,在其他情况下,我无需传递参数即可执行Action

最后,在XAML中,我需要执行如下命令:

    <Border.InputBindings>
        <MouseBinding MouseAction="LeftClick"
                      Command="{Binding SetLowPriorityCommand}"
                      CommandParameter="{Binding Source={x:Static core:PriorityLevel.Low}}"/> <!-- NOT ALWAYS NECESSARY -->
    </Border.InputBindings>

我找到了很多有关此问题的答案,但似乎没有一个使参数的使用成为可选项。

如何调整RelayCommand类以适应我的需求?

预先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

对代码的最简单的更改将只是使用一个object参数,并在调用方法时进行强制转换。否则,您可以在网上搜索并找到RelayCommand<T>的大量实现,但这是一个示例,该示例在您使用参数和不使用参数时都仅使用object参数。

public class RelayCommand : ICommand
{
    private Action<object> mAction;

    public event EventHandler CanExecuteChanged = (sender, e) => { };

    public RelayCommand(Action<object> action)
    {
        mAction = action;
    }

    public bool CanExecute(object parameter)
    {
        return true;

    }

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

public class ViewModel
{

    //ignore the argument
    private RelayCommand SetLowPriorityCommand { get => new RelayCommand(_ => SetLowPriority()); }

    //cast and use the argument
    private RelayCommand SetPriority { get => new RelayCommand(priority => SetPriority((int)priority)); }


    private void SetLowPriority()
    {
        //....///
    }

    private void SetPriority(int priority)
    {
        //...//
    }
}
相关问题