LightSwitch achievements: Chapter two (Events) – Classic events: “The observer”

In this blog post series, we’re going to create a fun extension that will stimulate the users of our LightSwitch applications by rewarding them with points and achievements when they use the application…

Also, in this particular post, I wrote my first VB.NET code ever, which seems to be the .NET language of choice of about 1/3rd of my readers… All comments on the VB.NET code will be considered positive feedback, no matter what you write or how you write it!

Functional POV

Conceptually, when talking about events in .NET, where are talking about a message that one object sends to zero-to-many other objects to let them know that something happened.  There’s four important elements here:

  • the sender (aka the source): the object that sends the message
  • the message: what happened
  • the timing: when did it happen
  • the event handlers (aka the listeners): the objects that want to take an action for the event

Most events will find their use in the presentation layer of our applications, where we want to execute code when the user clicks a button, hover the mouse cursor over an image, …

Semantics POV

It’s hard to talk code without a small example..

using System;

namespace ConsoleApplicationCSharp
{

    //1. Define the event "signature", usually (but NOT required) has two arguments: sender & event arguments.
    public delegate void ChangedEventHandler(object sender, EventArgs e);

    public class ClassWithEvent
    {
        //2. Define the event.
        public event ChangedEventHandler Changed;

        public void InvokeTheEvent()
        {
            Console.WriteLine("Firing the event");
            // 3. Invoking the event (can only be done from inside the class that defined the event)
            if (Changed != null)
                Changed(this, EventArgs.Empty);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var classWithEvent = new ClassWithEvent();
            //4. Adding an event handler to the event
            classWithEvent.Changed += new ChangedEventHandler(classWithEvent_Changed);
            classWithEvent.InvokeTheEvent();

            Console.ReadKey();
        }

        static void classWithEvent_Changed(object sender, EventArgs e)
        {
            Console.WriteLine("The event has fired");
        }
    }
}

And the same example in VB.NET (I think…)

Imports System

Namespace ConsoleApplicationVB

    '1. Define the event "signature", usually (but NOT required) has two arguments: sender & event arguments.
    Public Delegate Sub ChangedEventHandler(sender As Object, e As EventArgs)

    Public Class ClassWithEvent
        '2. Define the event.
        Public Event Changed As ChangedEventHandler

        Public Sub InvokeTheEvent()
            Console.WriteLine("Firing the event")
            ' 3. Invoking the event (can only be done from inside the class that defined the event)
            RaiseEvent Changed(Me, EventArgs.Empty)
        End Sub
    End Class

    Module Program

        Sub Main()
            Dim classWithEvent As New ClassWithEvent
            ' 4. Adding an event handler
            AddHandler classWithEvent.Changed, AddressOf classWithEvent_Changed
            classWithEvent.InvokeTheEvent()
            Console.ReadKey()
        End Sub

        Private Sub classWithEvent_Changed(sender As Object, e As EventArgs)
            Console.WriteLine("The event has fired")
        End Sub
    End Module

End Namespace

Just as the functional POV, the code samples reveal that when dealing with events, there are four important elements:

  1. What happened: the first step is to define the event “signature”, which happens in the form of a delegate.  There’s a lot of “standard” event signatures provided by the .NET framework and I would advise you to use them over custom events, but as the samples show, it’s really easy to roll your own.  Event signatures will often have two arguments: sender (a reference to the source, the object that raised the event), and (a subclass of) EventArgs (additional information about what happened).
  2. The sender: we add a property to the class that exposes the event, and add the .NET keyword “event”.  Conceptually, it’s ok to think of this property as a “collection of method references” that all match the signature from step1.  From a technical POV, what we actually do is add a property which is an empty delegate, aka method pointer that has no value yet.  On a traditional property, the compiler will generate two “subroutines”: “get” and “set”.  When we add the keyword “event” to the property declaration however, the compiler will add two “subroutines” called “add” and “remove”.  In the generated “add” subroutine, the value (new delegate) will be combined with the existing value, as opposed to a normal property, where the “set” will replace the existing value, and ofcourse the opposite happens in the “remove” “subroutine”.
  3. When it happened: raising the event is quite simple: do a null-reference check then call the delegate (C#, more technical) or use the (VB.Net, more descriptive) keyword RaiseEvent.  Conceptually, each method in our “collection of method references” from step 2 will be called.  Raising the event can only be done from inside the class that defined it, although often you will see classes that expose this functionality to anyone ( depending on the access modifier: private/public/…).
  4. The event handlers: these are the classes that subscribed to the event, in other words: told the sender they want to be notified when the event occurs, in the form of a method being called.  To do this, use the VB.Net keyword AddHandler, or the C# operator +=.  Both ways are just semantics that when compiled, result in the “add” subroutine from step 2 being called.

There’s a lot more technical aspects of events that I could discuss, the most important ones would be Garbage Collection (or more specifically: the prevention of GC on the event handlers) and thread safety, but let’s not forget that this is a LightSwitch blog, so let’s find out why this information is important for the Achievements extension that we are building in this blog post series…

LightSwitch POV

I wanted to take you in this shallow dive in events in .NET, because for our achievements extension, where most of the code resides in the model layer, not in the presentation layer, we’ll choose not to use this classic observer pattern, and use the event mediator pattern instead.  To justify exactly why we’ll go with a different pattern, it’s important to understand the conceptual and technical differences between the two…

However, the achievements extension will have a little bit of graphical artwork to it, and for this code (/XAML) there’s one event in particular that could use some special attention: INotifyPropertyChanged.

What’s INotifyPropertyChanged?

INotifyPropertyChanged is an interface that exposes just one property: the PropertyChanged event.  This event is extremely important in the MVVM pattern, because the bindings that we define in XAML recognize this event and will subscribe to it.  A Binding instance will update its value (“refresh the view”) if the source raises the event.

The viewmodel that implements this interface can use the PropertyChangedEventArgs in two ways:

  • Fill in the PropertyName: by doing this, the sender signifies to the listeners that one particular property has changed, and that all bindings on this property should update.
  • Leave the PropertyName blank: by doing this, the sender signifies to the listeners that the object changed so radically, that all bindings to any property on this object should update.  It’s basically requesting a general “refresh” of the view.
INotifyPropertyChanged has a brother called INotifyCollectionChanged, also recognized by bindings, useful for “ItemsSource” properties, …

An easy base class…

If you are using EME, (if you’re not: what the hell?) then there’s an easy base class included in the framework for your LightSwitch development convenience…

The ExtensionsMadeEasy.ClientAPI.Utilities.Base.NotifyPropertyChangedBase (source code here, it has been included for a while but never got around to blogging about it)  is a base class (based on the beautiful work by Rob Eisenberg) for your (/my) ViewModels. It exposes three (undocumented, sorry) methods:

namespace LightSwitchApplication
{
    public class SomeViewModel : ExtensionsMadeEasy.ClientAPI.Utilities.Base.NotifyPropertyChangedBase
    {
        private int myProperty;

        public int MyPublicProperty
        {
            get { return myProperty; }
            set {
                myProperty = value;
                base.Refresh(); //Refresh all bindings
                base.OnPropertyChanged("MyPublicProperty"); //Classic approach
                base.OnPropertyChanged(() => MyPublicProperty); //Approach with lambda expression
            }
        }        

    }
}

Or, in VB equivalent (I think…)

Public Class SomeViewModel
    Inherits ExtensionsMadeEasy.ClientAPI.Utilities.Base.NotifyPropertyChangedBase

    Private myProperty As Integer
    Public Property MyPublicProperty() As Integer
        Get
            Return MyProperty
        End Get
        Set(ByVal value As Integer)
            myProperty = value
            MyBase.Refresh() 'Refresh all bindings
            MyBase.OnPropertyChanged("MyPublicProperty") 'Classic approach
            MyBase.OnPropertyChanged(Function() MyPublicProperty) 'Approach with lambda expression
        End Set
    End Property

End Class

The first method (Refresh) raises the PropertyChanged event without a PropertyName on the EventArgs, all bindings on “SomeViewModel” will be refreshed.

The second method raises the PropertyChanged event with a hardcoded PropertyName (“MyPublicPropertyName”) on the EventArgs, all bindings on this property will be refreshed.  The string must match the actual property name exactly…

The third method does exactly the same as the second, but uses a lambda expression.  The major advantage is that the property is not hardcoded (ie: not a string), which gives you compile-time safety: you can not misspell the property name by accident or it won’t compile (happened to me many times before), but will also be updated automagically if you decide to refactor your class a bit, and rename the property.

To each his own of course, but I definitely prefer the latter.  Anyways, let’s see what this event mediator pattern is all about, and why it’s more suited for the model layer of our extension…

Advertisements

4 thoughts on “LightSwitch achievements: Chapter two (Events) – Classic events: “The observer”

  1. Pingback: Windows Azure and Cloud Computing Posts for 2/1/2012+ - Windows Azure Blog

  2. Does a lightSwitch app run as a single-threaded application on the UI thread or can/does model code and data access run on other threads?

    I’m used to seeing delegation back to the UI thread from other threads needing to be wrapped in an Invoke call or similar. Is this a non-issue for lightswitch? or just an advance on what’s posted here.

    • Hey Paul,
      AFAIK LightSwitch does have multiple trheads…
      Let me rephrase that, I regularly run into threading issues when doing some LightSwitch hacking! That’s why the EasyCommands have an overloaded constructor where you can specify the dispatcher… 🙂 I’m not sure if I’ll cover threading issues in a later blog post, I really have so much LightSwich specific material and there is some really good documentation on threading in .NET out there already…
      If you have some LightSwitch specific issues you are running into, feel free to let the community know / share some knowledge here!! 🙂

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