10

我有一个简单的窗口,带有一个按钮,它通过命令绑定到 ViewModel。

如果 MyCommand.CanExecute() 为假,我希望该按钮被禁用。但似乎 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="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 时应禁用该按钮?

4

2 回答 2

7

我看到您正在使用 Prism 及其NotificationObjectand DelegateCommand,所以我们应该期望 RaiseCanExecuteChanged() 中不会有错误。

但是,该行为的原因是 Prism 的 RaiseCanExecuteChanged 同步运行,因此 CanDoStuff()在我们仍在执行时调用,ICommand.Execute()结果似乎被忽略了。

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

或者,如果您使用 MVVM Light 和 RelayCommand 尝试相同的操作,您的代码将正常工作,因为 MVVM Light 的RaiseCanExecuteChanged调用会调用异步 usingCommandManager.InvalidateRequerySuggested()的回调,从而避免您在 Prism 的实现中看到的行为。CanDoStuffDispatcher.CurrentDispatcher.BeginInvoke

于 2013-02-22T22:40:38.263 回答
0

你可以试试这个(Microsoft.Practices.Prism.dll是必要的)

public class ViewModel
{
    public DelegateCommand ExportCommand { get; }

    public ViewModel()
    {
        ExportCommand = new DelegateCommand(Export, CanDoExptor);
    }

    private void Export()
    {
        //logic
    }

    private bool _isCanDoExportChecked;

    public bool IsCanDoExportChecked
    {
        get { return _isCanDoExportChecked; }
        set
        {
            if (_isCanDoExportChecked == value) return;

            _isCanDoExportChecked = value;
            ExportCommand.RaiseCanExecuteChanged();
        }
    }

    private bool CanDoExptor()
    {
        return IsCanDoExportChecked;
    }
}
于 2016-05-04T16:28:33.373 回答