当命令 CanExecute 为 false 时,按钮不会被禁用 [英] Button doesn't become disabled when command CanExecute is false

查看:20
本文介绍了当命令 CanExecute 为 false 时,按钮不会被禁用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的窗口,其中有一个按钮,通过命令绑定到 ViewModel.

I have a simple-as-can be window with a button tied to a ViewModel with a command.

如果 MyCommand.CanExecute() 为 false,我希望按钮被禁用.但似乎WPF只会在第一次绘制窗口时设置IsEnabled属性.任何后续操作都不会影响按钮的可见状态.我正在使用 Prism 的 DelegateCommand.

I expect the button to be disabled if MyCommand.CanExecute() is false. But it seems that WPF will only set the IsEnabled property when the window is first drawn. Any subsequent action does not effect the button's visible state. I am using a DelegateCommand from Prism.

我的观点:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Button Content="Click Here" Command="{Binding MyCommand}" Width="100" Height="50"/>
</Grid>

和我的视图模型:

public class MyVM : NotificationObject
{
    public MyVM()
    {
        _myCommand = new DelegateCommand(DoStuff, CanDoStuff);
    }

    private void DoStuff()
    {
        Console.WriteLine("Command Executed");
        _myCommand.RaiseCanExecuteChanged();
    }

    private bool CanDoStuff()
    {
        var result =  DateTime.Now.Second % 2 == 0;
        Console.WriteLine("CanExecute is {0}", result);
        return result;
    }

    private DelegateCommand _myCommand;

    public ICommand MyCommand
    {
        get
        {
            return _myCommand;
        }
    }
}

50% 的情况下,当我的应用程序加载时,按钮会被正确禁用.但是,如果它在窗口加载时启用,并且我单击按钮来执行命令,我希望该按钮有 50% 的时间被禁用,但它永远不会.该命令不执行,但我仍然可以单击该按钮.如何让 WPF 理解当 CanExecute() 为 false 时应禁用按钮?

50% of the time, when my application loads, the button is properly disabled. However, if it's enabled when the window loads, and I click the button to execute the command, I expect 50% of the time for the button to become disabled, but it never does. The command does not execute, but I can still click the button. How do I get WPF to understand that the button should be disabled when CanExecute() is false?

推荐答案

我看到你正在使用 Prism 及其 NotificationObjectDelegateCommand,所以我们应该期待那里没有成为 RaiseCanExecuteChanged() 中的一个错误.

I see you're using Prism and its NotificationObject and DelegateCommand, so we should expect there not to be a bug in RaiseCanExecuteChanged().

然而,这种行为的原因是 Prism 的 RaiseCanExecuteChanged 是同步运行的,所以 CanDoStuff() 在我们仍在 ICommand.Execute() 然后结果似乎被忽略了.

However, the reason for the behaviour is that Prism's RaiseCanExecuteChanged operates synchronously, so CanDoStuff() is called while we're still inside the implementation of ICommand.Execute() and the result then appears to be ignored.

如果您使用自己的命令创建另一个按钮并从该命令/按钮调用 _myCommand.RaiseCanExecuteChanged(),第一个按钮将按预期启用/禁用.

If you create another button with its own command and call _myCommand.RaiseCanExecuteChanged() from that command/button, the first button will be enabled/disabled as you expect.

或者,如果您对 MVVM Light 和 RelayCommand 尝试相同的操作,您的代码将起作用,因为 MVVM Light 的 RaiseCanExecuteChanged 调用 CommandManager.InvalidateRequerySuggested() 调用回调到 CanDoStuff 异步使用 Dispatcher.CurrentDispatcher.BeginInvoke,避免您在 Prism 的实现中看到的行为.

Or, if you try the same thing with MVVM Light and RelayCommand your code will work because MVVM Light's RaiseCanExecuteChanged calls CommandManager.InvalidateRequerySuggested() which invokes the callback to CanDoStuff asynchronously using Dispatcher.CurrentDispatcher.BeginInvoke, avoiding the behaviour you're seeing with Prism's implementation.

这篇关于当命令 CanExecute 为 false 时,按钮不会被禁用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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