当文档更改时在 postsharp [Command] 上触发 "CanExecute"?

Triggering "CanExecute" on postsharp [Command] when a document changes?

我目前正在将一个项目迁移到 PostSharp 以删除大量样板代码,大部分都进​​行得非常顺利,但我对如何强制命令重新检查感到困惑CanExecute。我希望 PostSharp 会像检查属性一样检查命令以检查依赖项,这是一个极简主义示例

[NotifyPropertyChanged]
public class MyWindowViewModel
{
    /// Anything bound to this refreshes just fine as expected
    public ObservableCollection<SomeType> Documents = new ObservableCollection<SomeType>();

   [Command]
   public ICommand AddDocumentCommand { get; set; }
   public void ExecuteAddDocument () { Documents.Add(new SomeType()); }

   [Command]
   public ICommand CloseDocumentCommand { get; set; }
   public bool CanExecuteCloseDocument () => Documents.Any(); 
   public void ExecuteCloseDocument () { Documents.Remove(Documents.Last()); }        
}

开始时集合是空的,关闭命令的按钮按预期显示为灰色,但是通过 AddDocument 的按钮添加文档不会激活关闭文档按钮,这是什么适当的方式来完成我需要的? PostSharp 是否只将赋值而不是方法调用视为更改,还是完全不同?

根据他们的 Command 文档

CanExecuteCloseDocument 应该是 属性

public bool CanExecuteCloseDocument => Documents.Any();

当命令需要参数时使用method选项,

The command availability check that depends on the input argument can be implemented as a method.

例如

public bool CanExecuteCloseDocument (int blah) => Documents.Any(); 
public void ExecuteCloseDocument (int blah) { Documents.Remove(Documents.Last()); }

除此之外,这里的主要问题是视图不知道集合的更改知道刷新 属性 更改。

参考这个http://www.postsharp.net/blog/post/Announcing-PostSharp-42-RC

Dependencies to collections

When you add the [AggregateAllChanges] attribute to a field or automatic property, any change to a property of the object assigned to this field/property will be interpreted as a change to the field/property itself. The attribute now works only for collections.

[NotifyPropertyChanged]
public class MyWindowViewModel {

    /// Anything bound to this refreshes just fine as expected
    [AggregateAllChanges] // <-- when the collection changes to cause notification
    public ObservableCollection<SomeType> Documents { get; } = new ObservableCollection<SomeType>();

   [Command]
   public ICommand AddDocumentCommand { get; set; }
   public void ExecuteAddDocument () { Documents.Add(new SomeType()); }

   [Command]
   public ICommand CloseDocumentCommand { get; set; }
   public bool CanExecuteCloseDocument => Documents.Any(); 
   public void ExecuteCloseDocument () { Documents.Remove(Documents.Last()); }        
}

使用 PostSharp LINQ 表达式 (or virtual calls, delegates, external methods) 不适用于 CanExecute。

但是实现 INotifyPropertyChanged 的​​属性的表达式非常棒(即使对于嵌套属性)。 ObservableCollection 实现了 INotifyPropertyChanged,我们不需要 LINQ:

public bool CanExecuteCloseDocument => Documents.Count > 0;