可选择将 T 类型的参数传递给 Action
Optionally pass a parameter of type T to an Action
我有一个名为 RelayCommand
的 class,它继承了如下定义的 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
}
我使用此 class 在整个应用程序中执行命令,有时我需要执行 Action
s 在 XAML 中传递参数。问题是这个参数传递是可选的,但我找不到适合我正在做的事情的解决方案。例如,我有这三个命令,它们基本上做同样的事情。我通过 UI 将 PriorityLevel
(enum
值)设置为对象,并根据单击的控件执行以下三种方法之一:
/// <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
s:
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>
我找到了很多关于这个的答案,但 none 似乎使用可选参数。
如何调整 RelayCommand
class 以满足我的需要?
提前感谢您的帮助。
对代码最简单的更改就是采用 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)
{
//...//
}
}
我有一个名为 RelayCommand
的 class,它继承了如下定义的 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
}
我使用此 class 在整个应用程序中执行命令,有时我需要执行 Action
s 在 XAML 中传递参数。问题是这个参数传递是可选的,但我找不到适合我正在做的事情的解决方案。例如,我有这三个命令,它们基本上做同样的事情。我通过 UI 将 PriorityLevel
(enum
值)设置为对象,并根据单击的控件执行以下三种方法之一:
/// <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
s:
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>
我找到了很多关于这个的答案,但 none 似乎使用可选参数。
如何调整 RelayCommand
class 以满足我的需要?
提前感谢您的帮助。
对代码最简单的更改就是采用 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)
{
//...//
}
}