Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Suppose the <code>CanExecuteChanged</code> event was implemented this way:</p> <pre><code>Private _handlers As New List(Of EventHandler)() Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged AddHandler(ByVal value as EventHandler) _handlers.Add(value) End AddHandler RemoveHandler(ByVal value As EventHandler) _handlers.Remove(value) End RemoveHandler RaiseEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) End RaiseEvent End Event </code></pre> <p>When an object listens to <code>CanExecuteChanged</code>, its handler is passed to <code>AddHandler</code> and is added to the list. This is basically how standard events are implemented.</p> <p>Suppose 2 buttons are both bound to the same command. They both listen to <code>CanExecuteChanged</code> so they can update their Enabled / Disabled state. Now you have references like this:</p> <pre><code>handler1 -&gt; button1 handler2 -&gt; button2 button1 -&gt; command -&gt; _handlers {handler1, handler2} button2 -&gt; command -&gt; _handlers {handler1, handler2} </code></pre> <p>If <code>button2</code> is removed from the screen, <code>command</code> is still in memory because <code>button1</code> is still bound to it. This means <code>_handlers</code> is also still in memory, which contains <code>handler2</code>. <code>handler2</code> references <code>button2</code>, so <code>button2</code> must remain in memory even though it shouldn't because it's no longer needed on screen. This is where the wasted memory issue can come from.</p> <p>The event can be implemented this way, though:</p> <pre><code>Public Custom Event CanExecuteChanged As EventHandler Implements ICommand.CanExecuteChanged AddHandler(ByVal value as EventHandler) AddHandler CommandManager.RequerySuggested, value End AddHandler RemoveHandler(ByVal value As EventHandler) RemoveHandler CommandManager.RequerySuggested, value End RemoveHandler RaiseEvent(ByVal sender As System.Object, ByVal e As System.EventArgs) End RaiseEvent End Event </code></pre> <p>In this implementation, the command does not store a list of handlers, so the above situation can't happen. Instead the handlers are passed to <code>CommandManager.RequerySuggested</code>. In other words, when a button requests to listen to <code>CanExecuteChanged</code>, it will actually be listening to <code>RequerySuggested</code>. This is usually acceptable because <code>RequerySuggested</code> is raised often and handlers are simple enough to not impact performance by being called often.</p> <p>There is also no memory issue to worry about here because <code>CommandManager.RequerySuggested</code> uses weak references.</p> <p>The only time you need a list of handlers (or a list of weak references to handlers) is if you want to use <code>RaiseCanExecuteChanged</code> to call them instead of relying on <code>CommandManager</code>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload