I recently started playing with Silverlight again, and wanted to share one way of doing MVC.

To keep things simple, I created an app that basically updates one textbox when you start typing something in the other (salary calculates taxes).

Let’s first go through the code at a high-level, and then walk through what actually happens sequentially behind the scenes.

Step 1: Define your model.

    public interface ICalculatorModel
    {
        double Salary { get; set; }
        double Taxes { get; set; }

        event EventHandler<CalculatorEventArgs> TaxesChanged;
    }

In MVC our model defines our data. Here we are saying we’ve got two pieces of information we are interested in (salary and taxes) and an event to notify people when one of these values change.

Here’s what the actual model looks like.

public class CalculatorModel : ICalculatorModel
    {
        private double salary;
        private double taxes;
        public readonly double TAX_RATE = 0.3d;

        public double Salary
        {
            get { return salary; }
            set
            {
                if (value == this.salary) return;
                salary = value;
                Taxes = salary*TAX_RATE;
            }
        }

        public double Taxes
        {
            get { return taxes; }
            set
            {
                if (value == this.taxes) return;
                taxes = value;
                OnTaxesChanged(new CalculatorEventArgs(this));
            }
        }

        public event EventHandler<CalculatorEventArgs> TaxesChanged;

        protected void OnTaxesChanged(CalculatorEventArgs e)
        {
            if (TaxesChanged != null)
                TaxesChanged(this, e); // fire event
        }
    }

It basically sets values for it’s properties, and fires off an event when someone changes the Taxes property value (this is the event our view registers for so it knows when to update it’s value on the screen).

Step 2: Define your view.

  public partial class CalculatorView : Page
    {
        private ICalculatorModel model;
        private ICalculatorController controller;

        public CalculatorView()
        {
            InitializeComponent();
        }

        public void SetModel(ICalculatorModel calculatorModel)
        {
            model = calculatorModel;
            SalaryTextBox.TextChanged += SalaryTextBoxChanged;
            model.TaxesChanged += ModelTaxesChanged;
        }

        private void ModelTaxesChanged(object sender, CalculatorEventArgs e)
        {
            TaxesTextBox.Text = e.Taxes.ToString();
        }

        private void SalaryTextBoxChanged(object sender, TextChangedEventArgs e)
        {
            controller.SetSalary(Double.Parse(SalaryTextBox.Text));
        }

        public void SetController(ICalculatorController calculatorController)
        {
            controller = calculatorController;
        }
    }

The view fires events off (letting models and controllers know when something interesting has happened). And it registers for events it is interested in (so it knows when to update itself).

In this example we are interested in two events:

  1. When does the SalaryTextBox text change.
  2. SalaryTextBox.TextChanged += SalaryTextBoxChanged;
    
  3. When does our model Taxes value change.
  4. model.TaxesChanged += ModelTaxesChanged;
    

Let’s now take a look at the controller.

Step 3: Hooking up the controller.

    public class CalculatorController : ICalculatorController
    {
        private CalculatorView view;
        private ICalculatorModel model;

        public CalculatorController(CalculatorView view, ICalculatorModel model)
        {
            this.view = view;
            this.model = model;

            view.SetModel(model);
            view.SetController(this);
        }

        public void SetSalary(double salary)
        {
            model.Salary = salary;
        }

        public void SetTaxes(double taxes)
        {
            model.Taxes = taxes;
        }
    }

The controller basically just coordinates things between the model and the view.
Here it passes on the setting of model values to the model itself (which then fires events telling people the model is changed).

But actual hookup for the controller occurs in the MainPage.xaml.cs code behind.

    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            ICalculatorModel model = new CalculatorModel();
            ICalculatorController controller = new CalculatorController(view, model);
        }
    }

That’s it for setup. Now let’s see how this all actually works.

Step 4: Let the events fly.

Because we have registered for the SalaryTextBox.TextChanged and model.TaxesChanged events in our view …

 public partial class CalculatorView : Page
    {
        public void SetModel(ICalculatorModel calculatorModel)
        {
            ...
            SalaryTextBox.TextChanged += SalaryTextBoxChanged;
            model.TaxesChanged += ModelTaxesChanged;
            ...
        }
}

when someone starts typing in the salary textbox

 public partial class CalculatorView : Page
    {
        private void SalaryTextBoxChanged(object sender, TextChangedEventArgs e)
        {
            controller.SetSalary(Double.Parse(SalaryTextBox.Text));
        }
}

our controller gets notified which passes the message onto our model

    public class CalculatorModel : ICalculatorModel
    {
        public double Salary
        {
             ...
            set
            {
                if (value == this.salary) return;
                salary = value;
                Taxes = salary*TAX_RATE;
            }
        }

        public double Taxes
        {
            ...
            set
            {
                if (value == this.taxes) return;
                taxes = value;
                OnTaxesChanged(new CalculatorEventArgs(this));
            }
        }
}

Now when the model sets it’s salary, it’s actually doing two things. First it sets the value of the salary if it’s changed, secondly it sets the Taxes property down below which in turn fires the OnTaxesChanged changed event:

    public class CalculatorModel : ICalculatorModel
    {
        protected void OnTaxesChanged(CalculatorEventArgs e)
        {
            if (TaxesChanged != null)
                TaxesChanged(this, e);
        }

This is how our Taxes textbox gets update. Because we registered for this event way back in our view, when it gets fired our Taxes textbox gets updated.

    public partial class CalculatorView : Page
    {
        private void ModelTaxesChanged(object sender, CalculatorEventArgs e)
        {
            TaxesTextBox.Text = e.Taxes.ToString();
        }

Phew!

That’s a lot of work to update one textbox based on the contents of another, but you could see how if you had a complicated UI, the benefits of separating the model from the view would start to pay off.

It jury is still out for me on how best to use MVC in Silverlight. Coming from a web background, all this eventing can get pretty confusing (the statelessness of the HTTP is nice).

But this is a start. I’ll post more when I get a chance to play with some other models like Model-View-Presenter.

You can download and play with source SilverLight-MVC here.

Note: WordPress doesn’t allow *.zip files so rename the *.doc to *.zip when you download.

You’ll need Visual Studios 2010 with Silverlight4.

In the mean time, here are some others Silverlight model view examples:

  1. Another MVC example.
  2. Model-View-Presenter example.
  3. Model-View-ViewModel example.
Advertisements