Silverlight MVVM pt 1: Hello World style


To Watch the Video of this post, click HERE

 

Holy crap, we have another freaking model to learn?

Yuppers.

Does it suck?

Nope, it makes things so much easier, it is a model that leverages what you already know.

What kinda stuff I already know?

You know about separation of concerns?

yup

You know about designing for testability?

yup

you know about the command pattern?

yup

you heard about Model View Controller pattern?

yup

Then you are set, this model leverages all of that, so it is only a matter of applying it and seeing how it all works in this new RIA world!

Silverlight Programming, How I Initially Want to do it

   Initially, I want to take all of my objects within the XAML, such as the textblocks and the buttons and what not, and I want to give them names and declaratively call them from my code behind. Then, I want to wire them up in my code behind with click events and so what have you. Lets see some of this stuff:

1. The xaml markup on the front end(just to get some UI out there):



br />











<

   A picture of the XAML from above is below:

xaml pic 1

2. I will be using a people service just to return a person object and then post that data to the UI (by the way, this is an outrageously contrived example that probably teaches you nothing…but we are getting somewhere)

namespace MVVM.HelloWorld
{
    public  class DummyPeopleService :IPeopleService
    {
        public  IList RetrievePeople()
        {
            IList people =  new List
                                        {
             new Person("Albert","al@foo.com", "Pujols", "STL", "63101"),
             new Person("Jose", "jo@foo.com", "Rodriquez", "LA", "90210"),
             new Person("John", "john@foo.com", "Franco", "NY", "123456")
                                        };
            return people;
                                   
        }
        public Person GetPersonByEmailAddress(string emailAddress)
        {
            IList people = RetrievePeople();
            return people.Where(p => p.EmailAddress == emailAddress).First();
        }
    }


    public interface IPeopleService
    {
         IList RetrievePeople();
         Person GetPersonByEmailAddress(string emailAddress);
    }
}

You could imagine what the person object looks like, but I'll go ahead and show it regardless:

 namespace MVVM.HelloWorld
{
    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string City { get; set; }
        public string Zip { get; set; }
        public string EmailAddress { get; set; }

        public Person(string firstName, string emailAddress, 
            string lastName, string city, string zip)
        {
            FirstName = firstName;
            LastName = lastName;
            City = city;
            Zip = zip;
            EmailAddress = emailAddress;
        }
    }
}

3. The code behind will just grab some data and then put values into the text boxes.This represents the old way of doing things, where we merely grab data and assign values to controls:

namespace MVVM.HelloWorld
{
    public partial class Page : UserControl
    {
        private IList people;
        public Page()
        {
            InitializeComponent();
            this.Loaded += Page_Loaded;
        }

        void Page_Loaded(object sender, RoutedEventArgs e)
        {
            IPeopleService svc = new DummyPeopleService();
            var person = svc.GetPersonByEmailAddress("al@foo.com");
            txt1.Text = person.FirstName;
            txt2.Text = person.LastName;
            txt3.Text = person.City;
            txt4.Text = person.Zip;
        }
    }

}


4. Below is a picture of this code running:

xaml pic 2

How to do the above with MVVM

    Now that we have done it one time by having ID’s on the elements and specifically putting values to them, lets try it in a different way. First off, I want to get rid of the x:Name attribute that is associated with each element, and I want to bind their text attributes to the value that I want them to bind to. Notice though that they have no clue where that data is coming from. All these textboxes know is that they are going to be getting a property sent their way that has a name that they are going to be looking for, like “FirstName,” or “LastName.” I am not defining a declarative type to show where they are coming from(like "person.FirstName”).
















  Now we get to the view model portion of this example. We will crate a view-model that will tie to the appropriate XAML file. For example, we have created an MVVMviewmodel, my default convention is to name it the same as the XAML usercontrol it represents, but just add a “viewmodel” to the end of it.

  You will notice from the code below that there are properties on this class that might be familiar from the binding  elements you saw earlier. This viewmodel does somethign interestesting, it accepts the usercontrol that it will be the DataContext for as a constructor (we will show how this all hooks in later).

namespace MVVM.PartOne
{

    public class MVVMviewmodel
    {
        private MVVM view;
        public string FirstName{ get; set;}
        public string LastName{ get; set;}
        public string City { get; set; }
        public string Zip { get; set; }
        private IPeopleService svc;
        public MVVMviewmodel(MVVM view, IPeopleService svc)
        {
            this.view = view;
            this.svc = svc;
            Initialize();    
        }
        private void Initialize()
        {
            var p = svc.GetPersonByEmailAddress("john@foo.com");
            FirstName = p.FirstName;
            LastName = p.LastName;
            City = p.City;
            Zip = p.Zip;
        }
    }
}

Below is the new code behind, it is much easier to define now, we are merely creating a new instance of the viewmodel and passing in the MVVM class. The values get bound by setting the Datacontext for the UserControl.

namespace MVVM.PartOne
{
    public partial class MVVM : UserControl
    {
        private readonly MVVMviewmodel vm;
        public MVVM()
        {
            InitializeComponent();

            vm = new MVVMviewmodel(this, new DummyPeopleService());
            DataContext = vm;
        }
    }
}

When this is ran, I get the same results as earlier:

xaml pic 3

   This is a HIGHLY contrived example of this in action, but we will move on to better examples in the future.

 

Hope this helps.

Ryan