WPF MVVM in VB.NET: Delegating Event Subscriptions for RoutedCommand (or any ICommand) in the ViewModel

Just started a new project in WPF. It’s my first WPF project and the firm’s first WPF project. Should be lots to blog about.

Stick One In His Eye

We are using MVVM because the WPF Pantheon (e.g. John Grossman, Josh Smith and Jason Dolinger) are in agreement that this pattern is eminently suited to WPF. So, yeah, we’re taking a bit of a Voodoo Architecture approach.

I am writing a Proof Of Concept using MVVM and found an absolutely brilliant video by Jason Dolinger here which shows a comprehensive refactoring example in MVVM while lucidly explaining the pattern. I was following the vid while coding my Proof Of Concept but got well and truly stuck on the part where Jason delegates (that’s del-e-GATEs as a verb) event subscriptions for the RoutedCommand in the ViewModel.

The Google To End All Googles

The reason I got stuck was that the vid is in C# whereas I am using VB.NET, which is not a problem in itself, but Jason was using C# Event Accessors to delegate the Event subscription. I had never heard of Event Accessors, Jason did not say what they were and VB.NET does not have them (at least not by that name).

I commenced a Google and soon saw that all the MSDN WPF examples are in C# only and not in VB.NET. I was looking for something I didn’t know the name of to do something I didn’t understand in a language which did not have the construct I needed. I was just about to wave a Dead Chicken at the monitor when, in the end Google did cough up an answer…in French. Impossible n’est pas français.

Here’s what had me stuck. What I needed was the VB.NET translation for this code

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}

First I had to figure out what the heck it was doing. Jason just said ‘now we have to wire the ICommand into the WPF Commanding system’ which left me very little the wiser. Well, ladies and gentlemen what you are witnessing above is the use of an Event Accessor to delegate (That’s del-e-GATE as a verb, not DEL-e-gate as a noun) event subscriptions.

In more detail, the ‘add’ Event Accessor is fired when an Event Subscription to CanExecuteChanged occurs. Value contains the Delegate i.e. Event Handler which is subscribing to the Event. Hence, the Event Handler denoted by value is being added to the Event Handler List for the CommandManager RequerySuggested event. This has the effect of wiring the WPF ICommand object that has that event subscription into the WPF Commanding infrastructure, thus allowing that ICommand to take effect.

VB.NET does not have Event Accessors but it does have a direct equivalent, namely Custom Events. Here’s the equivalent VB.NET code:


Public Custom Event CanExecuteChanged As EventHandler Implements System.Windows.Input.ICommand.CanExecuteChanged
AddHandler(ByVal value As EventHandler)
'This is the AddHandler block
AddHandler CommandManager.RequerySuggested, value
End AddHandler

RemoveHandler(ByVal value As EventHandler)
'This is the RemoveHandler block
RemoveHandler CommandManager.RequerySuggested, value
End RemoveHandler
'
RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
'This is the RaiseEvent block
CommandManager.InvalidateRequerySuggested()
End RaiseEvent
End Event

You can see its the same thing as a set of C# Event Accessors.

For the above code I am sobbing in helpless gratitude to binoo, moderateur of the WPF Forum at Devellopez.Com who posted the above code in this thread, entitled Modèle MVVM – Implémentation ICommand

What Are Custom Events ?

Mesdames and messuirs, you may read about Custom Events here. They enable custom handling of AddHandler, RemoveHandler and RaiseEvent calls for any event.

The above code, for example says that when AddHandler is called for a CanExecuteChanged event that the event handler for that event should be added to the RequerySuggested event of the CommandManager. The inverse happens for RemoveHandler and CommandManager.InvalidateRequerySuggested() is called when a RaiseEvent is done on a CanExecuteChanged event.

Further Reading

I will assume that anyone interested in this post knows about MVVM in WPF and why I would be wanting to wire up ICommand objects in the ViewModel, but for those who have heroically read this far without that pre-requisite knowledge, just click on the MVVM link at the start of the article and the one about the MVVM refactoring video.

And to binoo, now my favourite moderateur in the world, may your hovercraft be ever full of eels and your Brie only Triple Cream.

Advertisements

Tags: , ,

8 Responses to “WPF MVVM in VB.NET: Delegating Event Subscriptions for RoutedCommand (or any ICommand) in the ViewModel”

  1. Kerry Jenkins Says:

    Thank you for posting this. I was converting http://devlicio.us/blogs/rob_eisenberg/archive/2009/11/13/mvvm-study-part-4-naked-wpf.aspx from c# to vb and was stuck in the same way as you described. Your post helped a lot. Thanks!

    • baraholka1 Says:

      No problems Kerry,

      By the way that link you posted goes to a very useful set of tutorials.
      Thanks for that!

      – Barra

  2. Sean Liu Says:

    I was going through Josh Smith’s article on MVVM and had exactly the same problem. A Big Thank You for posting this finding!

    • baraholka1 Says:

      Hiya Sean,

      No probs. I read somewhere that MSDN will start putting up WPF examples in VB.NET. Hopefully that will be done by the Prism team too!

      – Barra

  3. Michael Bakker Says:

    Stuck in exact the same way as you, i found this article. Thanks for sharing!

    -Michael Bakker
    -Groningen, Holland

  4. Michael Bakker Says:

    A WPF routedevent example for VB.NET:

    Public Shared ReadOnly CancelClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(“CancelClick”, RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(MyCustomControl))

    Public Custom Event CancelClick As RoutedEventHandler
    AddHandler(ByVal value As RoutedEventHandler)
    MyBase.AddHandler(CancelClickEvent, value)
    End AddHandler
    RemoveHandler(ByVal value As RoutedEventHandler)
    MyBase.RemoveHandler(CancelClickEvent, value)
    End RemoveHandler
    RaiseEvent(sender As Object, e As RoutedEventArgs)
    End RaiseEvent
    End Event

    See also: http://www.dotnetcurry.com/ShowArticle.aspx?ID=569

    -Michael Bakker
    -Groningen, Holland

    • baraholka1 Says:

      Hi Michael,

      Thanks for dropping by and taking the trouble to add the useful example.
      Well BItten!

      – Barra

  5. Torsten Says:

    Thank you. I started with MVVM right now and your post helped me a lot.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


%d bloggers like this: