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?
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()); }
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With