Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am currently migrating a project to PostSharp to remove a lot of boilerplate code, most of it is going very smoothly but I'm left confused about how to force a command to recheck if it CanExecute. I expected PostSharp would inspect the command like it does properties to check for dependencies, here is a minimalist sample

[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()); }        
}

At start the collection is empty and the button attached to the close command is greyed as expected, however adding a document through the button attached to AddDocument doesn't activate the close document button, what is the appropriate way to accomplish what I need? Is PostSharp only considering assignments and not method calls as changes or is it something else entirely?

like image 606
Ronan Thibaudau Avatar asked Jul 11 '17 05:07

Ronan Thibaudau


1 Answers

According to their Command documentation

CanExecuteCloseDocument should be a property

public bool CanExecuteCloseDocument => Documents.Any();

The method option is used when the command requires parameters,

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

for example

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

That aside the main issue here is that the view is unaware of the changes to the collection to know to refresh property changes.

Refer to this 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()); }        
}
like image 70
Nkosi Avatar answered Oct 16 '22 11:10

Nkosi