The Model-View-Presenter is a great pattern for breaking apart separations of concerns in your applications.

The model holds your data and services.
The view holds your user interface controls and interactions.
The the presenter coordinates things behind the scenes.

It’s nice because it keep your business logic out the UI and it makes testing a lot easier as you can focus on just one layer of the application at a time.

Having used MVP a lot in ASP.NET applications, I wanted to see what it would look like in Silverlight and coded up this quick example for reference.

Let’s now see how MVP handles someone entering new user information on a page and hitting the save button.

The View

The view is our gateway into getting and controlling what the user sees on the screen.

UserAdminView.xaml

<UserControl x:Class="MVP1.View.UserAdminView" ...  d:DesignHeight="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="White">

        <ListBox ScrollViewer.VerticalScrollBarVisibility="Disabled">

            <TextBlock Text="Username"/>
            <TextBox Name="userNameTextBox" Width="100" Height="25" />
            <TextBlock Text="Roles" />

            <StackPanel Orientation="Horizontal">
                <CheckBox Name="RequestorCheckBox"  />
                <TextBlock Text="Requestor"/>
            </StackPanel>

            <StackPanel Orientation="Horizontal">
                <CheckBox Name="ApproverCheckBox"  />
                <TextBlock Text="Approver"/>
            </StackPanel>

            <Button Name="SaveButton" Content="Save" Click="SaveButtonClicked"/>
            <TextBlock Name="Message" Foreground="Green" Text="Success" Visibility="Collapsed"/>

         </ListBox>
    </Grid>
</UserControl>

When the user hits the save button we need to know what the users name is and what roles they are going to be assigned. To do that we might define a view interface that looks like this:

IUserAdminView.cs

    public interface IUserAdminView
    {
        string ReadName();
        IList ReadRoles();
        void DisplayMessage(string userName);
    }

… and gets implemented like this:

UserAdminView.xaml.cs

    public partial class UserAdminView : IUserAdminView
    {
        private readonly UserAdminPresenter presenter;

        public UserAdminView()
        {
            InitializeComponent();
            presenter = new UserAdminPresenter(this, new UserRepository());
        }

        public string ReadName()
        {
            return userNameTextBox.Text;
        }

        public IList<string> ReadRoles()
        {
            IList<string> roles = new List<string>();
            if (RequestorCheckBox.IsChecked == true)
                roles.Add("Requestor");
            if (ApproverCheckBox.IsChecked == true)
                roles.Add("Approver");
            return roles;
        }

        public void DisplayMessage(string userName)
        {
            Message.Visibility = Visibility.Visible;
            Message.Text = string.Format("{0} was successfully added.", userName);
        }

        private void SaveButtonClicked(object sender, RoutedEventArgs e)
        {
            presenter.HandleAddUser();
        }
    }

ReadName(), ReadRoles() and DisplayMessage() interact directly with the view and do pretty much what you’d expect.

The SaveButtonClicked event hanlder however is a bit different.

       private void SaveButtonClicked(object sender, RoutedEventArgs e)
        {
            presenter.HandleAddUser();
        }

Because the view isn’t really in a position to handle saving the user, it passes this request off to the presenter who can (he’s got the view for reading data and the model for saving it).

But before we get into that guy let’s take a quick look at the model.

The Model

 public interface IUserRepository
    {
        void AddUser(string username);
        void UpdateUserRoles(string username, IList<string> roles);
    }

The Model often goes by more than one name. Some call it the Service layer. My friends like Task. Here I’ve called it IUserRepository because all we’re going to do is save the user to the database.

This example doesn’t actually talk to any databases, but if it did that code would go here (or a more likely some backend webservice):

public class UserRepository: IUserRepository
    {
        public void AddUser(string username)
        {
            // add user to the database
        }

        public void UpdateUserRoles(string username, IList roles)
        {
            // update the user roles
        }
    }

That’s it for the model. It just does the actual work of whatever we want to do and is usually called from the presenter.

The Presenter

 public class UserAdminPresenter
    {
        private IUserAdminView view;
        private IUserRepository repos;

        public UserAdminPresenter(IUserAdminView view, IUserRepository repos)
        {
            this.view = view;
            this.repos = repos;
        }

        public void HandleAddUser()
        {
            string userName = view.ReadName();
            IList<string> roles = view.ReadRoles();

            if (!string.IsNullOrEmpty(userName))
            {
                repos.AddUser(userName);
                repos.UpdateUserRoles(userName, roles);
                view.DisplayMessage(userName);
            }
        }
}

The presenter is where we bring it all together. We use our view to get the data and the model to save it. It coordinates whatever is going on in your view.

In this case there’s only one thing we’re doing. Adding a user. So when the Save button gets pressed our view passes control over to the presenter and it goes about using the view and model to do just that.

        public void HandleAddUser()
        {
            string userName = view.ReadName();
            IList<string> roles = view.ReadRoles();

            if (!string.IsNullOrEmpty(userName))
            {
                repos.AddUser(userName);
                repos.UpdateUserRoles(userName, roles);
                view.DisplayMessage(userName);
            }
        }

That’s it. That’s all there is to MVP.

How is this different from any other MVP implementation?

Not much.

Any differences will usually be in platform. The stateless (request/response) nature of the web means web events come at HTTP Posts. In Silverlight they come as .NET WPF events.

Other than that they are pretty much the same.

How is this different from MVC?

It’s not really that much different. Thick client MVC implementations, in my experience, use a lot of eventing for communication. I don’t like that.

I find heavy eventing hard to follow and difficult to debug. So much happens behind the scenes it can be hard to see where you are in the program. This isn’t an MVC problem. It’s more an implementation style (see last post for an example of heavy eventing).

What I like about MVP (and MVC implementations like Rails and MVC.NET) is the simple request response enforced by statelessness of HTTP. Fire event, something happens, update controls.

If I can maintain that simplicity my Silverlight applications (less rather than more events) I will usually go for that.

What about MVVM?

That’s on my todo list next. I want to try the data binding that comes with that and see how that compares to MVC and MVP.

Stay tuned.

In the meantime, here’s an article to get you started on MVVM.

You can download the source here for this example here SilverLight-MPV.doc (rename *.doc to *.zip – wordpress limitation).