我有一个简单的窗口,带有一个带有命令的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>
和我的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%的时间,当我的应用程序加载时,按钮被正确禁用。但是,如果在窗口加载时启用它,并且我单击按钮执行命令,我希望该按钮有50%的时间被禁用,但它永远不会。该命令不会执行,但我仍然可以单击该按钮。当CanExecute()为false时,如何让WPF理解该按钮应该被禁用?
答案 0 :(得分:6)
我看到你正在使用Prism及其NotificationObject
和DelegateCommand
,因此我们应该期望RaiseCanExecuteChanged()中不会出现错误。
然而,行为的原因是Prism的RaiseCanExecuteChanged同步操作,因此当我们仍然在CanDoStuff()
的实现中时调用ICommand.Execute()
,然后结果似乎被忽略。
如果您使用自己的命令创建另一个按钮并从该命令/按钮调用_myCommand.RaiseCanExecuteChanged()
,则会按预期启用/禁用第一个按钮。
或者,如果您使用MVVM Light和RelayCommand尝试相同的操作,您的代码将起作用,因为MVVM Light的RaiseCanExecuteChanged
调用CommandManager.InvalidateRequerySuggested()
使用{{1}异步调用CanDoStuff
的回调,避免你在Prism的实现中看到的行为。
答案 1 :(得分: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;
}
}