异步 ICommand 实现
Async ICommand implementation
当我尝试在默认情况下执行时禁用命令时(即使没有向它传递 CanExecute 谓词),我的 asny ICommand 实现遇到了一个奇怪的行为。
public bool CanExecute(object parameter)
{
if (CanExecutePredicate == null)
{
return !mIsExecuting;
}
return !mIsExecuting && CanExecutePredicate(parameter);
}
public async void Execute(object parameter)
{
mIsExecuting = true;
await ExecuteAsync(parameter);
mIsExecuting = false;
}
我尝试引入一个私有布尔值,我在执行之前将其设置为 true,之后设置为 false。执行完成后设置 bool,但仅在单击鼠标按钮或移动鼠标或 w/e.
后才调用 CanExecute
现在我试着打电话
CanExecute(null);
在
之后
mIsExecuting = false;
但这也无济于事。我不知道我错过了什么。
感谢您的帮助
编辑:
为了澄清,我还为此 class 添加了构造函数:
public AsyncRelayCommand(Func<object, Task> execute)
: this(execute, null)
{
}
public AsyncRelayCommand(Func<object, Task> asyncExecute,
Predicate<object> canExecutePredicate)
{
AsyncExecute = asyncExecute;
CanExecutePredicate = canExecutePredicate;
}
protected virtual async Task ExecuteAsync(object parameter)
{
await AsyncExecute(parameter);
}
在异步场景中,WPF 往往不知道何时检查 CanExecute,这就是为什么你在 Icommand 接口中有 "CanExecuteChanged" 事件。
你的命令实现中应该有这样的东西:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
使用上面的代码,您现在可以执行此操作:
public async void Execute(object parameter)
{
mIsExecuting = true;
RaiseCanExecuteChanged ( ); // Not necessary if Execute is not called locally
await ExecuteAsync(parameter);
mIsExecuting = false;
RaiseCanExecuteChanged ( );
}
这将告诉 WPF 您想要刷新命令的 CanExecute 状态。
当我尝试在默认情况下执行时禁用命令时(即使没有向它传递 CanExecute 谓词),我的 asny ICommand 实现遇到了一个奇怪的行为。
public bool CanExecute(object parameter)
{
if (CanExecutePredicate == null)
{
return !mIsExecuting;
}
return !mIsExecuting && CanExecutePredicate(parameter);
}
public async void Execute(object parameter)
{
mIsExecuting = true;
await ExecuteAsync(parameter);
mIsExecuting = false;
}
我尝试引入一个私有布尔值,我在执行之前将其设置为 true,之后设置为 false。执行完成后设置 bool,但仅在单击鼠标按钮或移动鼠标或 w/e.
后才调用 CanExecute现在我试着打电话
CanExecute(null);
在
之后mIsExecuting = false;
但这也无济于事。我不知道我错过了什么。
感谢您的帮助
编辑:
为了澄清,我还为此 class 添加了构造函数:
public AsyncRelayCommand(Func<object, Task> execute)
: this(execute, null)
{
}
public AsyncRelayCommand(Func<object, Task> asyncExecute,
Predicate<object> canExecutePredicate)
{
AsyncExecute = asyncExecute;
CanExecutePredicate = canExecutePredicate;
}
protected virtual async Task ExecuteAsync(object parameter)
{
await AsyncExecute(parameter);
}
在异步场景中,WPF 往往不知道何时检查 CanExecute,这就是为什么你在 Icommand 接口中有 "CanExecuteChanged" 事件。
你的命令实现中应该有这样的东西:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
使用上面的代码,您现在可以执行此操作:
public async void Execute(object parameter)
{
mIsExecuting = true;
RaiseCanExecuteChanged ( ); // Not necessary if Execute is not called locally
await ExecuteAsync(parameter);
mIsExecuting = false;
RaiseCanExecuteChanged ( );
}
这将告诉 WPF 您想要刷新命令的 CanExecute 状态。