我有一个简单的 WPF 程序,带有ICommand
. 我发现该按钮没有像我预期的那样启用/禁用。我可以用一个人为的代码示例来最好地说明这一点:
class Reload : ICommand
{
private readonly BackgroundWorker _bworker = new BackgroundWorker();
public Reload()
{
this._isExecuting = false;
this._bworker.DoWork += this._bworker_DoWork;
this._bworker.RunWorkerCompleted += this._bworker_RunWorkerCompleted;
}
public event EventHandler CanExecuteChanged;
private void OnCanExecuteChanged()
{
if (this.CanExecuteChanged != null)
this.CanExecuteChanged(this, EventArgs.Empty);
}
private bool _isExecuting;
private void SetIsExecuting(bool isExecuting)
{
this._isExecuting = isExecuting;
this.OnCanExecuteChanged();
}
public bool CanExecute(object parameter)
{
return !this._isExecuting;
}
public void Execute(object parameter)
{
//this does not update the GUI immediately
this.SetIsExecuting(true);
//This line doesn't fix my problem
CommandManager.InvalidateRequerySuggested();
//during this wait, button appears "clicked"
Thread.Sleep(TimeSpan.FromSeconds(2)); //simulate first calculation
this._bworker.RunWorkerAsync();
}
private void _bworker_DoWork(object sender, DoWorkEventArgs e)
{
//during this wait, button appears disabled
Thread.Sleep(TimeSpan.FromSeconds(2)); //simulate second calculation
}
private void _bworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//this updates immediately
this.SetIsExecuting(false);
}
}
在该方法中,我以一种会导致返回 false的方式Execute(object)
触发事件。在那次通话之后,我希望该按钮立即被禁用,但直到调用之间的某个时间点它才会被禁用CanExecuteChanged
CanExecute(object)
RunWorkerAsync()
和第二次模拟计算之间的某个时间点才会被禁用。
在后台工作人员的RunWorkerCompleted(...)
事件处理程序中,我再次触发了CanExecuteChanged
事件,但这一次会导致CanExecuteChanged(object)
返回 true。在此调用之后,该按钮立即变为启用状态。
为什么当我触发CanExecuteChanged
事件时按钮没有立即显示为禁用?
注意#1:第一个模拟计算代表我应该在主 GUI 线程上运行的代码。如果我删除此调用,按钮将按预期运行。
注意#2:我已经阅读了有关使用CommandManager.InvalidateRequerySuggested()
强制代码调用该CanExecute(object)
方法的信息。我在我的评论中表明这对我不起作用。考虑到我打电话给OnCanExecuteChanged(...)
,我认为这个建议无论如何都是多余的。