Events Handling in MVVM

INTRODUCTION

Silverlight 4 comes with awesome features. It is been vastly improved from its previous versions. I think Microsoft is doing commendable job with every new release. Developing Line Of Business apps in this technology is a great. It has taken care of all the pit falls that the developers face in the earlier technologies. One of the major breakthrough is the support of Data Binding. Because of this extensive and improved data binding support developers can now easily develop the LOB apps using Model View ViewModel(MVVM) pattern. I tried to get my hands on it so I started converting one of my  application developed on WebForms technology to Silverlight 4 and I wanted to write the code using MVVM pattern, so that it becomes more testable. After completing this application I realize that I can now test my application without the UI. Great Stuff. While the development was underway I face one of the major challenge of Events Handling without violating the norms of MVVM patterns. Let us look into the problem in detail.

THE PROBLEM

I hope the readers of this post are aware of MVVM design pattern. There is no code-behind here,meaning you cannot write any code in (Filename.xaml.cs).Though this is not a hard bound rule but recommended by most of the MVVM experts. And I did not want to make any compromise with the pattern as I am firm believer of TDD. And MVVM patterns helps me in decoupling which enables me to write unit tests by creating mock-up objects of model and ViewModel. So now coming to the issue. As the application that I was redeveloping was Business Intelligence Tool which has all the filters displayed in the ListBox , where the user can select multiple items. At the bottom I wanted to show the user the items that they have selected in the ListBox. I wanted to achieve this with DataBinding Features of Silverlight. Though ListBox control in Silverlight natively supports the SelectedItems property. This property is not a dependent property hence it does not support INotifyPropertyChanged interface.Hence I could not bind this property to the my TextBlock Text property. I had a shortcut of using SelectionChanged event of the ListBox in the code behind and assigning the SelectedItems property to the TextBlock Text property. Huh not convincing to my heart. After spending few days doing some research on [Replace it with your favourite Search Engine :)]. I derived to the solution the way I wanted it to function. Let us look into it now.

THE SOLUTION

I found the solution which is an open source library on CodePlex site. Basically this library supports the data behaviour. Now you can declare your events in .xaml file and bind those events to the method in your ViewModel class. Cool, Isn’t it. So let me give you walkthrough of the entire solution

  1. Download the library Expression Blend Samples from CodePlex site.
  2. After the installation of the library , you have to add the reference of two assemblies in your Silverlight project as seen in the figure below.
    AssemblyRefrences
    Both the assemblies can be found in the Debug folder in the sample code zip file attached with this post.
  3. Now the next step is the add the namespace reference in your xaml
    xmlns:esi="clr-namespace:Expression.Samples.Interactivity;assembly=Expression.Samples.Interactivity"
    xmlns:swi="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
  4. Now we need to attach the SelectionChanged event to the ListBox, this is shown in the code below

    <ListBox x:Name="LstFruits" ItemsSource="{Binding FruitsCollection}" DisplayMemberPath="FruitName" SelectionMode="Multiple" Grid.Row="0" >
                <swi:Interaction.Triggers>
                    <swi:EventTrigger EventName="SelectionChanged">
                        <esi:CallDataMethod Method="LstFruits_SelectionChanged"/>
                    </swi:EventTrigger>
                </swi:Interaction.Triggers> 
    </ListBox>


    As seen in the above code I have binded the SelectionChanged event of the ListBox to the method LstFruits_SelectionChanged , which is the method in my ViewModel class.

  5. Let us now look at the LstFruits_SelectionChanged code

    public void LstFruits_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                foreach (object obj in e.AddedItems)
                {
                    Fruit f;
                    f = (Fruit)obj;
                    if (!objSelectedItems.Contains(f.FruitName))
                    {
                        objSelectedItems.Add(f.FruitName);
                    }
                }

                foreach (object obj in e.RemovedItems)
                {
                    Fruit f;
                    f = (Fruit)obj;
                    if (objSelectedItems.Contains(f.FruitName))
                    {
                        objSelectedItems.Remove(f.FruitName);
                    }
                }

                NotifyPropertyChanged("SelectedFruits");
            }


    The above code is super duper simple. Silverlight SelectionChangedEventArgs provides me with the array of AddedItems and RemovedItems properties. Using these properties I add or remove the items into my objSelectedItems class variable, which is List<string> type. Finally I have readonly property called SelectedFruits , which gets change notification as my ViewModel class implements INotifyPropertyChanged interface.

  6. Now finally let us look at the SelectedFruits readonly property code

    public string SelectedFruits
            {
                get
                {
                    var rtnVal = from s in objSelectedItems
                                 select s;
                    return string.Join(",", rtnVal.ToArray());
                }
            }


    This property returns me the string of comma separated items of the ListBox. It is binded to the TextBlock Text property

    <TextBlock Text="{Binding Path=SelectedFruits,StringFormat='Selected Fruits:{0}'}" Grid.Row="1" />

So with just few additional lines of code I was able to follow the MVVM pattern religiously.

CLOSURE

MVVM is a great pattern and should be strictly followed in your development of business apps whether you are using WPF or Silverlight. Finally a BIG thanks to Expression Blend team for their great work and contributions to the community. You can download the sample code of this post from here.

Hope this helps you, as always your feedback good or bad is highly appreciated. Cheers!

Advertisements

13 thoughts on “Events Handling in MVVM

  1. Very interesting. In silverlight 4 they have Commanding, but it is limited this opens up alot. Does it work with all the events supplied by the silverlight controls?

  2. I think this is an anti-pattern, as you are leaking View details into the ViewModel. Plus the whole approach of just shifting the code-handling to the ViewModel is plain wrong. One correct approach would be to have a behavior that handles the selection change, and then only pass back the selection data (i.e. Model) to the ViewModel, another approach could be to have an ICommand action married with an event trigger to pass back again only the selection data to the ViewModel.

      • Hi per your request, I’ve taken your sample and changed it to use an ICommand to relay the list selection to the ViewModel. You can download it from:

        http://www.orktane.com/nRoute/Downloads/MVVMEventHandling.zip

        Now, because I have the newer VS2010 RC (which doesn’t support SL4) I had to push down the application to SL3 version. As for the solution we basically execute a command when the selection changed event occurs, and we use the event trigger’s passed-in parameter to get the event args, have a look:


        The TriggerParameterConverter converts your SelectionChangedEventArgs to IEnumerable using an IValueConverter. Though in this specific case we don’t actually use of added/removed items (which you could), but given your use, I just returned the all the selected items as a parameter of the ICommand.

        Also, this makes use of a newer version of nRoute Toolkit, which I’ll blog about in depth later. And remember this is just one possible solution, alternatively you could have written a behavior to handle the selection changed stuff by itself.

        Hope this helps.

      • Thanks Rishi for your solution

        Looks like need to do some hands on nroute framework, which makes great use of behaviours

  3. Hello goldytech,

    I put it into my code and works perfectly, great!.

    But i put it into a dataform and it doesn´t works, do you know some way
    to work into a dataform.

    Thank you,

    Fausto

    • Hello Fausto,
      Honestly speaking I haven’t used DataForm much, becuase as a developer I lose control on most of things. And other big reason is that it does not aid much in MVVM pattern.But I assume this technique should work with DataForm also. Try to use NewItemTemplate property of the DataForm and define your form in it.
      Hope this helps.

      Thanks
      Goldy

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