2

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?

dmigo
  • 2,849
  • 4
  • 41
  • 62
  • What about your `CanExecuteChangedHandler`? How does it look like? Is this a method or a lambda expression? – dymanoid Jan 22 '15 at 22:26

1 Answers1

2

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;
dmigo
  • 2,849
  • 4
  • 41
  • 62