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

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

问题描述



我希望如果MyCommand.CanExecute可以禁用该按钮,我可以使用一个简单的可以是窗口与一个按钮绑定到一个ViewModel。 ()为false。但是似乎WPF只会在窗口第一次绘制时设置IsEnabled属性。任何后续操作不会影响按钮的可见状态。我使用Prism的DelegateCommand。



我的视图:

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



和我的ViewModel: p>

  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时应该禁用按钮?

解决方案

使用Prism及其 NotificationObject DelegateCommand ,因此我们应该期望在RaiseCanExecuteChanged()中不会有错误。



但是,这种行为的原因是Prism的RaiseCanExecuteChanged同步操作,因此调用 CanDoStuff() 're仍然在执行 ICommand.Execute(),然后结果似乎被忽略。



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



或者,如果你尝试与MVVM Light和RelayCommand相同的事情,你的代码将工作,因为MVVM Light的 RaiseCanExecuteChanged 调用 CommandManager.InvalidateRequerySuggested()其使用异步调用 CanDoStuff 的回调Dispatcher.CurrentDispatcher.BeginInvoke ,避免了你在Prism的实现中看到的行为。


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

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.

My View:

<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>

and my ViewModel:

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% 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?

解决方案

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

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.

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.

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天全站免登陆