Wpf 按钮不存在';当命令CanExecute为false时,t变为禁用
我有一个简单的窗口,带有一个按钮,通过命令绑定到ViewModel 如果MyCommand.CanExecute()为false,我希望该按钮被禁用。但WPF似乎只会在第一次绘制窗口时设置IsEnabled属性。任何后续操作都不会影响按钮的可见状态。我正在使用来自Prism的DelegateCommand 我的看法是: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
<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;
}
}