Reputation: 3029
I have two ViewModels and one contains another. The inner one has a Microsoft.Practices.Prism.Commands.DelegateCommand
called PrintCommand
. It is desirable to subscribe to the CanExecuteChanged
event of this command. This part is implemented as usual:
OneViewModel.PrintCommand.CanExecuteChanged += CanExecuteChangedHandler;
The problem is that this subscription doesn't work.
Decompiled CanExecuteChanged
looks like this:
public event EventHandler CanExecuteChanged
{
add
{
WeakEventHandlerManager.AddWeakReferenceHandler(ref this._canExecuteChangedHandlers, value, 2);
}
remove
{
WeakEventHandlerManager.RemoveWeakReferenceHandler(this._canExecuteChangedHandlers, value);
}
}
When I debug, after a couple of steps after subscription the _canExecuteChangedHandlers
doesn't seem to contain any alive handlers, even though subscriber object still exists.
I'm kind of curious, why is it happening?
Upvotes: 2
Views: 399
Reputation: 3029
The answer was found in the description of CanExecuteChanged
. Here it is:
/// When subscribing to the <see cref="E:System.Windows.Input.ICommand.CanExecuteChanged"/> event using
/// code (not when binding using XAML) will need to keep a hard reference to the event handler. This is to prevent
/// garbage collection of the event handler because the command implements the Weak Event pattern so it does not have
/// a hard reference to this handler. An example implementation can be seen in the CompositeCommand and CommandBehaviorBase
/// classes. In most scenarios, there is no reason to sign up to the CanExecuteChanged event directly, but if you do, you
/// are responsible for maintaining the reference.
This means that we should have a hard reference:
private readonly EventHandler commandCanExecuteChangedHandler;
And use it like this:
this.commandCanExecuteChangedHandler = new EventHandler(this.CommandCanExecuteChanged);
this.command.CanExecuteChanged += this.commandCanExecuteChangedHandler;
Upvotes: 2