【问题标题】:Triggering "CanExecute" on postsharp [Command] when a document changes?文档更改时在 postsharp [Command] 上触发“CanExecute”?
【发布时间】:2017-07-11 05:19:36
【问题描述】:

我目前正在将一个项目迁移到 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 是否仅将分配而不是方法调用视为更改,还是完全不同?

【问题讨论】:

    标签: c# .net wpf postsharp


    【解决方案1】:

    根据他们的Command 文档

    CanExecuteCloseDocument 应该是一个属性

    public bool CanExecuteCloseDocument => Documents.Any();
    

    命令需要参数时使用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

    对集合的依赖

    当您将[AggregateAllChanges] 属性添加到字段或 自动属性,对分配给的对象的属性的任何更改 此字段/属性将被解释为对 字段/属性本身。该属性现在仅适用于集合。

    [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 5,命令文档很空,但是成功了,并且得到了清楚的解释,谢谢
    • 参考这篇帖子有一个类似的问题,我从 PostSharp 支持中得到了这个答案:“由于 NPC 方面的内部限制,[AggregateAllChanges] 不适用于集合,我们知道这个问题。提升命令的CanExecuteChanged 事件目前是不可能的......除了使用反射(ICommand 实现对象具有 OnCanExecute(object) 方法)之外,我没有看到任何其他方式来引发事件。对于给您带来的不便,我深表歉意"
    【解决方案2】:

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

    但是实现 INotifyPropertyChanged 的​​属性上的表达式效果很好(即使对于嵌套属性)。 ObservableCollection 实现了 INotifyPropertyChanged,我们不需要 LINQ:

    public bool CanExecuteCloseDocument =&gt; Documents.Count &gt; 0;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-07
      • 1970-01-01
      • 1970-01-01
      • 2011-08-26
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      相关资源
      最近更新 更多