【发布时间】:2011-01-20 20:34:40
【问题描述】:
我的应用程序是使用 WPF 中的 MVVM 模式编写的,并且我的所有按钮都使用命令绑定来执行我的模型中的代码。所有命令在 CanExecute 中都有代码来确定绑定的 Button 的 Enabled 状态。该逻辑运行良好,但在所有情况下,除非我单击 GUI 中的其他位置,否则 GUI 始终处于禁用状态。
例如,我有一个名为 Discard Candy 的按钮。当我单击此按钮时,它会在线程池线程中启动一个进程,该进程将名为 Running 的布尔属性设置为 true。由于 Discard Candy 命令的 CanExecute 方法看起来像这样
public bool CanExecute(object parameter)
{
return !Running;
}
一旦进程开始,该按钮将被禁用。问题是,当该过程完成时,Running 被设置为 false,但 GUI 不会更新,即 Discard Candy 不会重新启用。
但是,如果我单击 GUI 中的任意位置,例如窗口或标题栏,“丢弃糖果”按钮会突然启用。所以逻辑有效,但发生了一些我不明白的事情。有人可以向我解释一下这种行为吗?
编辑 -- 到目前为止,听起来 CommandManager.InvalidateRequerySuggested 并没有帮助到人们。我打算试一试,但目前我有点警惕。我确实遵循了推荐的链接,因此决定阅读更多关于 MVVM 轻量级工具包的信息。听起来非常不错——这里有没有人使用过它并且能够确认它没有出现我迄今为止看到的问题?虽然我计划在下一个主要版本中尝试 MVVM 轻量级工具包。在我的应用程序中,我不想重做我目前拥有的所有命令,这就是为什么我可能会从 CommandManager.InvalidateRequerySuggested 开始,这样我们就可以在这里获得另一个关于它有用性的数据点。
EDIT #2 -- 非常有趣,MVVM 轻量级工具包实际上依赖 CommandManager.InvalidateRequerySuggested 以支持 UI 禁用/重新启用命令的能力。作者说:
“严格来说,在 WPF 中,如果您的命令绑定到由 CommandManager 监视的控件,则您不必自己引发 CanExecuteChanged 事件。您可以让 CommandManager 处理这种情况。也就是说,外部事件也可能改变 UI 的状态。假设 UI 应该从上午 9 点到下午 5 点启用,然后在晚上禁用。用户没有触发 UI,因此代码应该(礼貌地)请求 CommandManager重新查询命令的状态。这是通过在 CommandManager 上调用 InvalidateRequerySuggested 方法来完成的。正如您所猜到的,RelayCommand 类的 RaiseCanExecuteChanged 方法就是这样做的。"
【问题讨论】:
-
你能显示将 Running 设置为 false 的代码吗?是不是在线程完成后的回调中?
-
设置 Running 时是否为命令提升 CanExecuteChanged?
-
@John:在工作流完成后,Running 被设置为 false,这在指定事件被设置时是已知的。 @itowlson:我的印象是一切都会“神奇地起作用”。当我在学习这些东西时,我在 CanExecute 中放置了一个断点,它总是被击中......但我想这只是因为当我按下 F5 时,GUI 重新绘制,然后导致 CanExecute 再次被调用。傻我!
-
我遇到了同样的行为,执行 CommandManager.InvalidRequerySuggested 并没有帮助。我很好奇你是怎么解决这个问题的。由于这个问题,我们最终手动禁用。
-
我见过的唯一一次 InvalidateRequerySuggested 不起作用是它是从 Dispatcher 以外的另一个线程执行的。除此之外,它工作正常。
标签: wpf data-binding mvvm command