.net 有没有一种干净的方法可以使CanExecute始终使用属性返回true?

.net 有没有一种干净的方法可以使CanExecute始终使用属性返回true?,.net,wpf,data-binding,attributes,.net,Wpf,Data Binding,Attributes,我想我已经知道我的问题的答案了,但我还是想说出来。我有一个拥有大量命令处理程序的应用程序,每个程序的CanExecute方法中都有特殊的逻辑,可以适当地启用绑定按钮 现在我不想执行任何逻辑,因为执行会导致对库的调用,我不想仅仅为了GUI更新而调用库。我无法删除库调用,因为它们对于应用程序其余部分的功能非常重要 我研究了.NET中的条件属性,遗憾的是,这不起作用,因为它们只适用于返回void的方法。我可以使用#if和#define来使用我的逻辑或返回true。我还可以查询viewmodel中的属性

我想我已经知道我的问题的答案了,但我还是想说出来。我有一个拥有大量命令处理程序的应用程序,每个程序的CanExecute方法中都有特殊的逻辑,可以适当地启用绑定按钮

现在我不想执行任何逻辑,因为执行会导致对库的调用,我不想仅仅为了GUI更新而调用库。我无法删除库调用,因为它们对于应用程序其余部分的功能非常重要

我研究了.NET中的条件属性,遗憾的是,这不起作用,因为它们只适用于返回void的方法。我可以使用#if和#define来使用我的逻辑或返回true。我还可以查询viewmodel中的属性,并允许它确定是否只返回true


问题是,我并不懒惰,但我也不想做一大堆繁重的工作,以使修改,我猜是不可避免的。但是,如果有人知道一种方法可以使用.NET中的某些内容自动启用我的按钮,而无需调用CanExecute或至少避免使用底层逻辑,请发布答案!)

我不知道是否有使用属性的方法,但是试试这个。在窗口的某个位置,启动代码循环遍历所有命令绑定,并为每个命令绑定处理
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
}

我质疑为什么调用这个库来获取GUI逻辑是不好的。您不希望启用无法执行任何操作的按钮,因此在命令无法实际工作时禁用这些命令可能是一件好事

使用MVVM模式时,我的ViewModels通常直接公开ICommand。如果使用Prism,则有一个DelegateCommand实现,可以轻松地在ViewModels中实现这些命令。如果没有,或者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。

程序员编写程序为其执行繁重的工作;-)有趣的是,我从未编写过修改源代码的程序。我总是编写实用程序来生成测试数据或执行其他类型的繁重工作,但不使用我的源代码。我可能应该这么做,嗯。:)哦,太棒了!今晚我要试一试。谢谢Brian,通常如何从ViewModel中获取CommandBindings?属性
CommandBindings
位于
窗口中,因此您需要在窗口中循环它们,或者将属性传递给视图模型,我想。很抱歉,响应太晚-我确实在窗口中查看了CommandBindings,但是集合是空的。所以一定有某个物体在某个地方包含了所有的元素。我会做一些搜索。原因很简单,只要窗口重新绘制,所有按钮的CanExecute方法都会被调用,调用到一个与物理设备对话的库中。这将导致通信总线上的额外通信量,如果不需要,我们不想对其进行筛选。您所说的关于iCommand的内容很有趣。到目前为止,我已经用两种方法完成了按钮处理程序:实现按钮单击事件处理程序,以及将按钮绑定到ICommand。从您所说的内容来看,听起来好像您在使用ICommands,但不要使用CanExecute/Execute。你能告诉我这个方法的方向吗,因为我以前没有见过它?我想这就是你认为我在做的:,但我使用的是ICommands。是的,当你说“命令绑定”时,我认为你在对RoutedCommands进行命令绑定。我将更新答案以反映您的情况。谢谢更新,Abe。让我确认一下,我明白你在说什么。视图绑定到的ExpensiveCommand只是将其所有操作委托给从IExpensiveService继承的东西。这个“昂贵的服务”存在于ViewModel中,然后可能通过VM中的某个参数来决定命令是否可以执行;因此,ExpensiveCommand也会知道,但逻辑不需要存在。总的来说,对所有命令禁用CanExecute的“覆盖”行为似乎是同样的工作量。(续)