我想我已经知道了我的问题的答案,但无论如何我想把它放在那里。我有一个带有大量命令处理程序的应用程序,每个命令处理程序在其CanExecute方法中都有特殊逻辑,以适当地启用绑定按钮。
现在我处于一种我不希望执行任何逻辑的情况,因为执行会导致调用我不想发生的库仅用于GUI更新 。我不能删除库调用,因为它们对应用程序其余部分的功能非常重要。
我查看了.NET中的条件属性,遗憾的是,这不起作用,因为它们只能处理返回void的方法。我可以使用#if和#define来使用我的逻辑或只返回true。我还可以查询viewmodel中的属性,并允许它确定是否只返回true。
问题是,我不是很懒,但我也不想做一堆咕噜咕噜的工作来做出我猜的修改是不可避免的。但是,如果有人知道如何在.NET中使用某些东西来自动启用我的按钮而无需调用CanExecute或至少避免使用底层逻辑,请发布答案! :)
答案 0 :(得分:1)
我怀疑为什么用GUI逻辑调用这个库是不好的。您不希望启用不执行任何操作的按钮,因此在无法实际工作时禁用的命令可能是件好事。
使用MVVM模式时,我的ViewModel通常会直接公开ICommands。如果使用Prism,则会有一个DelegateCommand实现,可以在ViewModel中轻松实现这些命令。如果没有,或者CanExecute可能会改变,我会在一个单独的类中实现ICommand。
如果您有长时间运行/昂贵的操作,您始终可以缓存库调用的结果。我假设如果状态改变将启用/禁用命令,您将获得事件或回调。在这种情况下,在ICommand实现中,您将引发CanExecuteChanged事件,以便GUI反映对命令的更改。下面是一个使用支持服务的命令示例,该支持服务知道何时可以完成操作:
public class ExpensiveCommand : ICommand
{
private readonly IExpensiveService service;
private bool canExecute;
public ExpensiveCommand (IExpensiveService service)
{
this.service = service;
canExecute = service.CanExecute();
service.CanExecuteChanged += OnCanExecuteChanged;
}
public void Execute(object parameter)
{
service.Execute();
}
public bool CanExecute(object parameter)
{
return canExecute;
}
public event EventHandler CanExecuteChanged;
private void OnCanExecuteChanged(object sender, EventArgs e)
{
canExecute = service.CanExecute();
if (CanExecuteChanged != null)
CanExecuteChanged(this, EventArgs.Empty);
}
}
或者,如果您始终希望命令可执行,则可以从CanExecute方法返回true。
答案 1 :(得分:0)
我不知道是否有一种属性的方法,但试试这个。在窗口的某处,启动代码循环遍历所有命令绑定,并为每个命令绑定处理PreviewCanExecute
事件。
public MainWindow()
{
foreach (CommandBinding cb in CommandBindings)
{
cb.PreviewCanExecute += new CanExecuteRoutedEventHandler(cb_PreviewCanExecute);
}
}
void cb_PreviewCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = false; // disable / enable all commands
e.Handled = true; // Set this to skip calling your existing logic
}