除非鼠标被点击,否则Button不会重新启用的奇怪问题 [英] Weird problem where Button does not get re-enabled unless the mouse is clicked

查看:200
本文介绍了除非鼠标被点击,否则Button不会重新启用的奇怪问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序是使用WPF中的MVVM模式编写的,我的所有按钮都使用命令绑定来执行我的模型中的代码。所有命令都有CanExecute中的代码来确定绑定的Button的Enabled状态。该逻辑工作完美,但在所有情况下,GUI仍处于禁用状态,除非我点击GUI中的其他位置。



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

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

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



但是,如果我点击GUI中的任何位置,就像在窗口或标题栏上,丢弃糖果按钮突然启用。所以逻辑是有效的,但事情正在发生,我只是不明白。有人可以向我解释这个行为吗?



编辑 - 到目前为止,听起来像CommandManager.InvalidateRequerySuggested没有帮助人。我要给它一个镜头,但在这一刻,我有点担心。我确实遵循了推荐的链接,并且这样做决定阅读更多关于MVVM灯光工具包。这听起来很好,很好 - 有人在这里使用它,并且能够确认它没有显示我目前为止看到的问题吗?虽然我打算在下一个主要版本中尝试使用MVVM Light Toolkit。在我的应用程序中,我不想重做我目前所有的命令,这就是为什么我可能从CommandManager.InvalidateRequerySuggested开始,所以我们可以在这里获得另一个数据点,这是有用的。 >

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



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

解决方案

WPF不更新命令绑定控件,除非有理由。单击GUI会导致WPF刷新,以便更新然后起作用。



您可以手动导致任何命令绑定控件的刷新,方法是调用 CommandManager.InvalidateRequerySuggested


My app is written using the MVVM pattern in WPF, and all of my Buttons use Command bindings to execute code in my model. All commands have code in CanExecute to determine the bound Button's Enabled state. The logic works perfectly, but in all cases, the GUI remains in a disabled state unless I click somewhere else in the GUI.

For example, I have a button called Discard Candy. When I click this button, it launches a process in a threadpool thread, which sets a bool property called Running to true. Since the CanExecute method for Discard Candy's command looks something like this

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

the button will be disabled once the process starts. The problem is that when the process is done, Running gets set to false, but the GUI doesn't update, i.e. Discard Candy doesn't get re-enabled.

However, if I click anywhere in the GUI, like on the window or title bar, the Discard Candy button all of a sudden gets enabled. So the logic works, but something is going on that I just don't understand. Can someone please explain this behavior to me?

EDIT -- so far, it sounds like CommandManager.InvalidateRequerySuggested hasn't helped people. I am going to give it a shot, but at the moment am a little wary of it. I did follow the recommended links, and in doing so decided to read more about the MVVM light toolkit. It sounds very nice -- has anyone here used it and been able to confirm that it does not exhibit the problem I've been seeing so far? Although I plan to try the MVVM light toolkit in the next major rev. of my application, I don't want to redo all of the commanding that I currently have in place, which is why I'll likely start with CommandManager.InvalidateRequerySuggested so we can all get another data point here regarding it's usefulness.

EDIT #2 -- very interesting, the MVVM light toolkit actually relies on CommandManager.InvalidateRequerySuggested in order to support the UI's ability to disable / re-enable commands. The author says:

"Strictly speaking, in WPF, and if your command is bound to a control that is watched by the CommandManager, you shouldn’t have to raise the CanExecuteChanged event yourself. You can let the CommandManager handle the situation. That said, external events might also change the state of the UI. Let’s imagine that the UI should be enabled from 9AM to 5PM, and then disabled for the night. The user is not triggering the UI, so the code should request (politely) that the CommandManager requeries the state of the commands. This is done by calling the method InvalidateRequerySuggested on the CommandManager. And as you guessed, the method RaiseCanExecuteChanged of the RelayCommand class does just that."

解决方案

WPF doesn't update command bound controls unless it has a reason to. Clicking on the GUI causes WPF to refresh so the update then works.

You can manually cause a refresh of any command bound controls by calling CommandManager.InvalidateRequerySuggested.

这篇关于除非鼠标被点击,否则Button不会重新启用的奇怪问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆