Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 按钮不存在';当命令CanExecute为false时,t变为禁用_Wpf_Mvvm_Command_Prism - Fatal编程技术网

Wpf 按钮不存在';当命令CanExecute为false时,t变为禁用

Wpf 按钮不存在';当命令CanExecute为false时,t变为禁用,wpf,mvvm,command,prism,Wpf,Mvvm,Command,Prism,我有一个简单的窗口,带有一个按钮,通过命令绑定到ViewModel 如果MyCommand.CanExecute()为false,我希望该按钮被禁用。但WPF似乎只会在第一次绘制窗口时设置IsEnabled属性。任何后续操作都不会影响按钮的可见状态。我正在使用来自Prism的DelegateCommand 我的看法是: <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/w

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

如果MyCommand.CanExecute()为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="MainWindow" Height="350" Width="525">
<Grid>
    <Button Content="Click Here" Command="{Binding MyCommand}" Width="100" Height="50"/>
</Grid>

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

我看到您使用的是Prism及其
NotificationObject
DelegateCommand
,因此我们应该认为RaiseCanExecuteChanged()中不会出现错误

然而,出现这种行为的原因是Prism的RaiseCanExecuteChanged是同步运行的,因此当我们还在
ICommand.Execute()
的实现中时,调用了
CanDoStuff()
,然后结果似乎被忽略

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

或者,如果您尝试使用MVVM Light和RelayCommand执行相同的操作,您的代码将正常工作,因为MVVM Light的
RaiseCanceChanged
调用了
CommandManager.InvalidateRequestSuggested()
,它使用
Dispatcher.CurrentDispatcher.BeginInvoke
异步调用对
CanDoStuff
的回调,避免您在Prism的实现中看到的行为。

您可以尝试此操作(
Microsoft.Practices.Prism.dll
是必需的)


您需要做的第一件事是为数据绑定打开调试消息:接下来,重新运行并检查输出窗口,看看有什么错误。如果与命令绑定无关,那么
raisecancecutechanged()
的实现是不正确的/buggy。您的CanDOStuff方法真的很奇怪!它可以使您的按钮被禁用,但在下一秒您的命令可以执行,但按钮被禁用。。。真的很奇怪。但是如果您的CanExecute可能被更改,并且UI没有更新,您应该打电话,因为CanExecuteChanged没有被引发。@Viktor我知道这真的很奇怪,这应该是一个随机返回真/假的愚蠢示例。CommandManager.InvalidateRequestSuggested无效。@输出中是否没有错误,并且
RaiseCanceTechChanged
是Microsoft Prism库的一部分,不是自行生成的。谢谢您的解释。我试过你的两个建议,它们都很恰当。这似乎是棱镜的一个不幸限制。
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;
        }
    }
}
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;
    }
}