Events Handling in MVVM

Goldytech
Posted by in Silverlight category on for Beginner level | Views : 22249 red flag

This article teaches you how can handle events in Model View ViewModel ( MVVM) pattern without using the code behind model. Sample project is attached.
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!

Page copy protected against web site content infringement by Copyscape

About the Author

Goldytech
Full Name: Muhammad Afzal Qureshi
Member Level: Bronze
Member Status: Member
Member Since: 8/4/2009 10:58:17 PM
Country: India

http://goldytech.wordpress.com
Hello Everyone Myself Muhammad Afzal , aka GoldyTech. Thats my pen name. I reside in India and work as a solution Architect on .NET platform. I hope you must have enjoyed reading my blog. Please leave your comments or suggestions good or bad and help me to improve

Login to vote for this post.

Comments or Responses

Login to post response

Comment using Facebook(Author doesn't get notification)