MVVM pattern in Silverlight using SLEextensions

In this  article I will explain how to implement MVVM pattern in Silverlight.

I was very overjoyed when I was reading my friends article on Codeproject about MVVM pattern in WPF .

You can check this article by Miroslav Popovic on http://www.codeproject.com/KB/WPF/FirefoxLikeSearchWithMVVM.aspx

I have decided to try implement same pattern in Silverlight .After reading and researching about MVVM pattern and his implementation in Silverlight I have found that most used method for implementing something close to MVVM in Silverlight is done by using SLEextension libraries.

SLEextension libraries you can found on Codeplex at this adress : http://www.codeplex.com/SLExtensions

When we talk about MVVM pattern and his implementation we must mention concept of attached behaviors and what is main purpose of MVVM pattern.

The Attached Behavior pattern encapsulates “behavior” (usually user interactivity) into a class outside the visual heirarchy and allows it to be applied to a visual element by setting an attached property and hooking various events on the visual element.(definition by John Gossman)

Main concept of MVVM pattern is to shrink or completly remove logic from the presentation.More about these patterns you can read from links below.

There are many ways to implement attached behavior in Silverlight.You can use SilverlightFX libraries from Nikhil Kothari or something else but most easiest way to do this is to use SLEextensions library.

I will show you now how to implement this on small exemple project.I have created form with button, textbox and  datagrid control.Main purspose of this form is when you enter searh text and press search button grid is populated with filtered data.

Picture1_thumb

First we need to add reference to SLExtensions.dll.After that we need to create static class Commands where we need to put all our methods.We now create our method GetData.Whery important thing is to create static void Initialize to ensure later that static fields are initialized.

This class looks like this :

public static class Commands

    {

        static Commands()

        {

            GetData = new Command(“GetData”);

        }

        public static Command GetData

        {

            get;

            private set;

        }

        ///<summary>

        /// Ensure static fields are initialized

        ///</summary>

        public static void Initialize()

        {

        }

    }

After that we need to create base class for all ViewModels.It looks like this :

public abstract class ViewModel : INotifyPropertyChanged

    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)

        {

            if (PropertyChanged != null)

                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

    }

and PersonViewModel class that has some important things.

In constructor PersonViewModel class we set what method will be responsible when GetData method executes.In setter or public property List we must set OnPropertyChanged method to occcur.

public class PersonViewModel:ViewModel

    {

        private List<Person> list;

        public string City { get; set; }

        public List<Person> List

        {

            get { return list; }

            set

            {

                list = value;

                OnPropertyChanged(“List”);

            }

        }

        public PersonViewModel(string CityP)

        {

           City = CityP;

           Commands.GetData.Executed+=new System.EventHandler<ExecutedEventArgs>(GetData_Executed);

        }

        void GetData_Executed(object sender, ExecutedEventArgs e)

        {

            List = Model.Person.GetPeople();

            var query = from c in List

                        where c.City.ToLower().StartsWith(City.ToLower())

                        select c;

            List=query.ToList();

        }

    }

In xaml file we need to add reference to

xmlns:Input=clr-namespace:SLExtensions.Input;assembly=SLExtensions

and set what method will be attached to button control.

Input:CommandService.Command=GetData Input:CommandService.CommandParameter={Binding}

After that only two things more we must do.First we need to ensure that before proccesing xaml file static commands are created,and we need to on button click event pass PersonViewModel to Datacontext element to populate dataGrid control.

        public Page()

        {

            // Ensure static commands are created before xaml is processed

            Commands.Initialize();

            InitializeComponent();

        }

        private void btnOK_Click(object sender, RoutedEventArgs e)

        {

            DataContext = new PersonViewModel(txtSearch.Text);

        }

I hope this will be good starting point for you to try to implement this pattern in your own projects. I think that reasons for implementing this pattern are obvious (testibility, separation from presentation layer…) but debbuging  is very big problem for everybody try to use this pattern in real Silverlight application.

Demo project: SilverlightMVVM

 

Source :

Attached behavior pattern :

http://blogs.msdn.com/johngossman/archive/2008/05/07/the-attached-behavior-pattern.aspx

http://www.nikhilk.net/Silverlight-Behaviors.aspx

http://blogs.southworks.net/jdominguez/2008/08/icommand-for-silverlight-with-attached-behaviors/

MVVM pattern :

http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx

http://blogs.msdn.com/dancre/archive/2006/10/11/datamodel-view-viewmodel-pattern-series.aspx

http://www.nikhilk.net/Silverlight-ViewModel-Pattern.aspx

http://tozon.info/blog/post/2009/01/20/Silverlight-TreeView-MVVM-and-editing-1.aspx

http://mark-dot-net.blogspot.com/2008/11/model-view-view-model-mvvm-in.html

  • http://codemind.blogspot.com/ Miroslav Popovic

    Hi Radenko,

    Glad you liked my article :) I was also playing recently with Silverlight and MVVM, but approached this problem slightly different.

    One important thing missing from Silverlight is Commanding support, so that was the first thing to implement. I used Commands class from Composite Application Guidance for WPF and Silverlight: http://www.codeplex.com/CompositeWPF. This class defines Command and CommandParameter attached properties for ButtonBase similar to WPF ones. The same class is used in SLExtensions.

    Instead of having static class holding all commands like you have, my commands are in their respective ViewModels. So, if I have CustomersPage with Add and Update buttons, I’ll have AddCommand and UpdateCommand in CustomersViewModel, defined as public non-static properties and initialized in CustomersViewModel’s constructor.

    View (CustomerPage) binds to that commands like this: <Button Content="Add" Infrastructure:Commands.Command="{Binding AddCommand}" />. Code behind is absolutely empty, except in case of main page where it sets the page DataContext in constructor.

  • http://blog.developers.ba/ Radenko Zec

    Great Miroslav.Thanks for sharing.

  • Pratik Mehta

    Hi Miroslav Popovic,

    I referred Commands class from Composite Application Guidance for WPF and Silverlight, but i dont get idea how to use it, can you please suggest.

    Thanks

  • http://codemind.blogspot.com/ Miroslav Popovic

    Hi Pratik,

    This is how I used it in one of my projects…

    Commands class was defined in Abacus.Invoicer.Infrastructure namespace (your namespace may differ).
    You first need to define XML namespace in your Page.xaml like this:
    <Page xmlns:Infrastructure="clr-namespace:Abacus.Invoicer.Infrastructure" …

    Then you can define commands in Page.xaml like this:
    <Button
    Infrastructure:Commands.Command="{Binding InvoicesCommand}"
    Content="Invoices"
    />

    You can also specify additional command parameter like this:
    <Button
    Infrastructure:Commands.Command="{Binding InvoicesCommand}"
    Infrastructure:Commands.CommandParameter="{Binding [i]someViewModelProperty[/i]}"
    Content="Invoices"
    />

    Since I was using MVVM pattern for that project, InvoicesCommand was defined in PageViewModel class.

    Hope this helps.

  • Pratik Mehta

    Hi Miroslav Popovic,

    Thanks for the reply, and sorry for late repling, i used commands in my viewmodel classes and it worked fine first time but when i use that page second time it gives me error that the command is already exists.. do you have any idea about that?

    Thanks again

  • Pratik Mehta

    There is very big bug in slextension. see below link.

    http://silverlight.net/forums/t/99409.aspx