gpt4 book ai didi

c# - 如何使用 CommandManager 并且仍然能够手动触发 ICommand.CanExecuteChanged 事件,即明确地?

转载 作者:行者123 更新时间:2023-11-30 22:04:41 24 4
gpt4 key购买 nike

我给自己写了一个 SingleExecutionCommand(我还不确定那个名字。请随意推荐另一个,但这不是我的问题),它不允许在第一次执行之前再次按下按钮完成的。好吧,至少那是计划。
我想使用 CommandManager处理我的 CanExecuteChanged-Event,但我还需要在更改 ExecutionIsRunning 时自行触发此事件-旗帜。

这是我的指令代码:

public class SingleExecutionCommand<T> : DelegateCommand<T>
{

protected readonly Func<T, Task> AwaitableExecuteDelegate;

public bool ExecutionIsRunning { get; protected set; }

public SingleExecutionCommand(Func<T, Task> awaitableExecute, Predicate<T> canExecute = null) :
base(null, canExecute)
{
AwaitableExecuteDelegate = awaitableExecute;
}

public SingleExecutionCommand(Action<T> execute, Predicate<T> canExecute = null)
: base(execute, canExecute)
{
AwaitableExecuteDelegate = null;
}

public async override void Execute(object parameter)
{
if (parameter != null && !(parameter is T)) throw new ArgumentException("Command Parameter has the wrong type.");

if (AwaitableExecuteDelegate == null)
{
ExecutionIsRunning = true;
base.Execute(parameter);
ExecutionIsRunning = false;
}
else
{
ExecutionIsRunning = true;
await AwaitableExecuteDelegate((T)parameter);
ExecutionIsRunning = false;
}
}

public override bool CanExecute(object parameter)
{
return (!ExecutionIsRunning) && base.CanExecute(parameter);
}
}

如果在我的 DelegateCommand<T> 中尝试这样做-类:

protected void FireCanExcuteChangedEvent()
{
if (CanExecuteChanged == null) return;

CanExecuteChanged(this, EventArgs.Empty);
}

但这不起作用,因为该事件是重新路由的事件(到 CommandManager.RequerySuggested )而不是真实事件。那么,我怎样才能同时使用 CommandManager和我自己的事件?

编辑:
CanExecuteChanged -事件看起来像这样:

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

最佳答案

由于处理程序被分配/委托(delegate)给 CommandManager.RequerySuggested 事件,我建议调用 CommandManager.InvalidateRequerySuggested()。这将引发 CanExecuteChanged 事件以表示有关命令有效性的条件已更改。所有监听器现在将重新评估它们是否可以通过响应 CanExecute() 调用来执行命令。如果结果为 false,通常会禁用命令源。

您的固定 FireCanExcuteChangedEvent() 将如下所示:

protected virtual void FireCanExcuteChangedEvent()
{
CommandManager.InvalidateRequerySuggested();
}

请注意,这将引发全局 CanExecuteCHanged 事件,即在每个 ICommand 实例上(其中 CanExecuteCHanged 事件调用委托(delegate)给 命令管理器)。如果性能是一个问题,请考虑为每个实例显式提高 CanExecuteChanged(参见下面的示例)。

改进的实现将引入专用的内部事件委托(delegate)。除了将它们委托(delegate)给 CommandManager.RequerySuggested 事件之外,此委托(delegate)还将累积 CanExecuteChanegd 订阅者的事件处理程序。
这样你就有了两种选择:

  • 根据全局CommandManager.RequerySuggested事件通知事件观察者
  • 根据本地通知,即 CanExecuteChanged 的实例事件版本(独立于 CommandManager.RequerySuggested)。

以下示例还允许禁用基于 CanExecuteChanged 事件的 CommandManager 调用。
这样,命令必须通过调用公共(public)InvalidateCommand() 方法显式无效:

public class RelayCommand : ICommand
{
// Optional feature:
// Allow to bypass the CommandManager completely
// to use explicit command invalidation only (via the public InvalidateCommand method).
// Set from constructor.
public bool IsCommandManagerInvalidateRequeryEnabled { get; }

// Store CanExecuteChanged event handlers
// to invoke them independent from the CommandManager
private EventHandler canExecuteChangedDelegate;

public RelayCommand(bool isCommandManagerInvalidateRequeryEnabled)
{
this.IsCommandManagerInvalidateRequeryEnabled = isCommandManagerInvalidateRequeryEnabled ;
}

// Invalidate this command explicitly.
// Raises the ICommand.CanExecuteChanged event of this instance.
public void InvalidateCommand() => OnCanExecuteChanged();

/// Raises the ICommand.CanExecuteChanged event.
protected virtual void OnCanExecuteChanged()
=> this.canExecuteChangedDelegate?.Invoke(this, EventArgs.Empty);

// Explicit event implementation
public event EventHandler CanExecuteChanged
{
add
{
if (this.IsCommandManagerInvalidateRequeryEnabled)
{
// Delegate the CanExecuteChanged event invocation to the CommandManager
CommandManager.RequerySuggested += value;
}

// Accumulate handlers on a local delegate
// to allow raising the CanExecuteChanged event independent of the CommandManager
this.canExecuteChangedDelegate += value;
}
remove
{
CommandManager.RequerySuggested -= value;
this.canExecuteChangedDelegate -= value;
}
}
}

关于c# - 如何使用 CommandManager 并且仍然能够手动触发 ICommand.CanExecuteChanged 事件,即明确地?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25030612/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com