奇怪的问题,除非单击鼠标,否则不会重新启用Button

时间:2010-02-25 04:24:11

标签: wpf data-binding mvvm command

我的应用程序是使用WPF中的MVVM模式编写的,我的所有按钮都使用Command绑定来执行模型中的代码。所有命令都在CanExecute中具有代码,以确定绑定Button的Enabled状态。逻辑运行完美,但在所有情况下,除非我点击GUI中的其他位置,否则GUI将保持禁用状态。

例如,我有一个名为Discard Candy的按钮。当我单击此按钮时,它会在线程池线程中启动一个进程,该线程将名为Running的bo​​ol属性设置为 true 。由于Discard Candy命令的CanExecute方法看起来像这样

public bool CanExecute(object parameter)
{
  return !Running;
}

进程启动后,该按钮将被禁用。问题是,当流程完成后,Running会设置为 false ,但GUI不会更新,即Discard Candy不会重新启用。

但是,如果我点击GUI中的任何位置,例如在窗口或标题栏上,则会立即启用Discard Candy按钮。所以逻辑是有效的,但事情正在发生,我只是不明白。有人可以向我解释一下这种行为吗?

编辑 - 到目前为止,听起来像CommandManager.InvalidateRequerySuggested并没有帮助别人。我打算试一试,但此刻我有点担心。我确实按照推荐的链接,这样做决定阅读更多有关MVVM光工具包的信息。这听起来非常很好 - 有没有人在这里使用它并且能够确认它没有表现出我到目前为止看到的问题?虽然我计划在下一个主要版本中尝试MVVM轻型工具包。在我的应用程序中,我不想重做我目前所拥有的所有命令,这就是为什么我可能会从CommandManager.InvalidateRequerySuggested开始,所以我们都可以在这里得到另一个关于它有用的数据点。

编辑#2 - 非常有趣,MVVM光工具包实际上依赖在CommandManager.InvalidateRequerySuggested上,以支持UI禁用/重新启用命令的能力。作者说:

“严格地说,在WPF中,如果你的命令绑定到CommandManager监视的控件,你不必自己引发CanExecuteChanged事件。你可以让CommandManager处理这种情况。那就是说,外部事件也可能会改变UI的状态。让我们假设UI应该从上午9点到下午5点启用,然后在晚上禁用。用户没有触发UI,所以代码应该(礼貌地)请求CommandManager重新查询命令的状态。这是通过在CommandManager上调用方法InvalidateRequerySuggested来完成的。正如您猜测的那样,RelayCommand类的方法RaiseCanExecuteChanged就是这样做的。

3 个答案:

答案 0 :(得分:20)

WPF不会更新命令绑定控件,除非它有理由。单击GUI会导致WPF刷新,因此更新可以正常工作。

您可以通过调用CommandManager.InvalidateRequerySuggested手动刷新任何命令绑定控件。

答案 1 :(得分:3)

我的问题似乎与命令绑定绑定了 - 我经常使用RelayCommand但是在我点击一个窗口之前,按钮的渲染是不正确的。

CanExecute中移除CommandBinding代码并使用IsEnabled属性代替解决了我的问题而没有头疼 - 它只是花了很长时间,直到我在许多其他事情中尝试这个可能是问题。

答案 2 :(得分:0)

有时,将焦点设置在父控件上会使CommandManager触发CanExecute。将Running设置为false后尝试以下操作:

...
Running = false;
parentControl.Focusable = true;
parentControl.Focus();