MVP In Silverlight/WPF

MVP In Silverlight/WPF: Some Infrastructure Bits

17 commentsWritten on August 2nd, 2010 by
Categories: MVP In Silverlight/WPF

Note: This post is part of a series. You can find the introduction and overview of the series here.

In the previous post, we discussed the different parts this client-side architecture is composed of. Before we can start using these parts effectively in our code, we'll need some infrastructural base classes that we can inherit from. In this post, we'll cover base classes for the View, the Presenter and the BindingModel. I'm also going to briefly discuss how various user controls can communicate with each other without being directly coupled to each other, and how we'll communicate with the Model (which is a Service Layer in this series and its accompanying sample).

Let's start off with the BindingModel. In the previous post of this series, i said that the BindingModel is supposed to facilitate data binding. So what exactly does that mean? Well, that means that the BindingModel is responsible for everything that's required to take full advantage of Silverlight/WPF's data binding features. In the case of Silverlight, that means at least implementing INotifyPropertyChanged and raising the necessary events at the right time, and if you want to use client-side validation that works together with the data binding features, the INotifyDataErrorInfo interface. Note: this interface is not available yet in WPF but you can use the IDataErrorInfo interface to do something similar (though far less elegantly).

In our case, the BindingModel implements both INotifyPropertyChanged and INotifyDataErrorInfo. Tom Ceulemans (who still doesn't have a blog i can link to, which is too bad because he'd put many Silverlight 'experts' and book authors to shame), a coworker of mine, recently wrote something that makes it incredibly easy to elegantly use simple client-side validation in combination with data binding. So before i can show you the base BindingModel class, i need to show a small utility class that will be used by our BindingModel:

    public class PropertyValidation<TBindingModel>
        where TBindingModel : BindingModel<TBindingModel>
    {
        private Func<TBindingModel, bool> validationCriteria;
        private string errorMessage;
        private readonly string propertyName;
 
        public PropertyValidation(string propertyName)
        {
            this.propertyName = propertyName;
        }
 
        public PropertyValidation<TBindingModel> WithMessage(string errorMessage)
        {
            if (this.errorMessage != null)
            {
                throw new InvalidOperationException("You can only set the message once.");
            }
 
            this.errorMessage = errorMessage;
            return this;
        }
 
        public PropertyValidation<TBindingModel> When(Func<TBindingModel, bool> validationCriteria)
        {
            if (this.validationCriteria != null)
            {
                throw new InvalidOperationException("You can only set the validation criteria once.");
            }
 
            this.validationCriteria = validationCriteria;
            return this;
        }
 
        public bool IsInvalid(TBindingModel presentationModel)
        {
            if (validationCriteria == null)
            {
                throw new InvalidOperationException("No criteria have been provided for this validation. (Use the 'When(..)' method.)");
            }
 
            return validationCriteria(presentationModel);
        }
 
        public string GetErrorMessage()
        {
            if (errorMessage == null)
            {
                throw new InvalidOperationException("No error message has been set for this validation. (Use the 'WithMessage(..)' method.)");
            }
 
            return errorMessage;
        }
 
        public string PropertyName
        {
            get { return propertyName; }
        }
    }

This class basically makes it possible to define the validation for a property of your BindingModel with a nice fluent syntax. I'll show you an example of this, right after i show you the BindingModel base class in its entirety:

    public abstract class BindingModel<TBindingModel> : INotifyPropertyChanged, INotifyDataErrorInfo
        where TBindingModel : BindingModel<TBindingModel>
    {
        public event PropertyChangedEventHandler PropertyChanged = delegate { };
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged = delegate { };
 
        private readonly List<PropertyValidation<TBindingModel>> validations = new List<PropertyValidation<TBindingModel>>();
        private Dictionary<string, List<string>> errorMessages = new Dictionary<string, List<string>>();
 
        protected BindingModel()
        {
            PropertyChanged += (s, e) => { if (e.PropertyName != "HasErrors") ValidateProperty(e.PropertyName); };
        }
 
        public IEnumerable GetErrors(string propertyName)
        {
            if (errorMessages.ContainsKey(propertyName)) return errorMessages[propertyName];
 
            return new string[0];
        }
 
        public bool HasErrors
        {
            get { return errorMessages.Count > 0; }
        }
 
        public void ValidateAll()
        {
            var propertyNamesWithValidationErrors = errorMessages.Keys;
            ClearAllErrorMessages();
 
            validations.ForEach(PerformValidation);
            var propertyNamesThatMightHaveChangedValidation = errorMessages.Keys.Union(propertyNamesWithValidationErrors).ToList();
            propertyNamesThatMightHaveChangedValidation.ForEach(NotifyErrorsChanged);
 
            NotifyPropertyChanged(m => m.HasErrors);
        }
 
        public void ValidateProperty(Expression<Func<TBindingModel, object>> expression)
        {
            ValidateProperty(GetPropertyName(expression));
        }
 
        private void ValidateProperty(string propertyName)
        {
            ClearErrorMessagesForProperty(propertyName);
            validations.Where(v => v.PropertyName == propertyName).ToList().ForEach(PerformValidation);
            NotifyErrorsChanged(propertyName);
            NotifyPropertyChanged(m => m.HasErrors);
        }
 
        protected PropertyValidation<TBindingModel> AddValidationFor(Expression<Func<TBindingModel, object>> expression)
        {
            var validation = new PropertyValidation<TBindingModel>(GetPropertyName(expression));
            validations.Add(validation);
            return validation;
        }
 
        private void NotifyErrorsChanged(string propertyName)
        {
            ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
        }
 
        private void PerformValidation(PropertyValidation<TBindingModel> validation)
        {
            if (validation.IsInvalid((TBindingModel)this))
            {
                AddErrorMessageForProperty(validation.PropertyName, validation.GetErrorMessage());
            }
        }
 
        private void AddErrorMessageForProperty(string propertyName, string errorMessage)
        {
            if (errorMessages.ContainsKey(propertyName))
            {
                errorMessages[propertyName].Add(errorMessage);
            }
            else
            {
                errorMessages.Add(propertyName, new List<string> { errorMessage });
            }
        }
 
        private void ClearAllErrorMessages()
        {
            errorMessages = new Dictionary<string, List<string>>();
        }
 
        private void ClearErrorMessagesForProperty(string propertyName)
        {
            errorMessages.Remove(propertyName);
        }
 
        protected void NotifyPropertyChanged(string propertyName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
 
        protected void NotifyPropertyChanged(Expression<Func<TBindingModel, object>> expression)
        {
            NotifyPropertyChanged(GetPropertyName(expression));
        }
 
        private static string GetPropertyName(Expression<Func<TBindingModel, object>> expression)
        {
            MemberExpression memberExpression;
 
            if (expression.Body is UnaryExpression)
            {
                memberExpression = ((UnaryExpression)expression.Body).Operand as MemberExpression;
            }
            else
            {
                memberExpression = expression.Body as MemberExpression;
            }
 
            if (memberExpression == null)
            {
                throw new InvalidOperationException("You must specify a property!");
            }
 
            return memberExpression.Member.Name;
        }
    }

That's quite a bit huh? It's not really all that much though. Here's what this class does:

  • gives us a type-safe way of raising the PropertyChanged event based on an expression
  • when a PropertyChanged event is raised, we automatically validate that property if a validation for that property has been defined
  • provides a very easy way to define validations for properties
  • enables you to validate all properties (for which validations have been defined), or just a specific one
  • takes full advantage of the INotifyDataErrorInfo functionality of Silverlight which means that as soon as a property doesn't validate, the UI will show this to the user automatically without us having to do anything for it

For instance, suppose we have a Name property that is bound to a TextBox using two-way binding. We can define the validation of the Name property like this:

           AddValidationFor(m => m.Name)
                .When(m => string.IsNullOrWhiteSpace(m.name))
                .WithMessage("name is a required field");

And the Name property would be implemented like this:

        private string name;
 
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                NotifyPropertyChanged(m => m.Name);
            }
        }

That's it. If the user (or you) puts an invalid value in the Name property, the InputControl that is bound to it will automatically display the validation message. If the user (or you) puts a valid value in the Name property, its validation message will automatically be removed by the InputControl. You'll see some extensive examples of BindingModels once we explore how to build our User Controls in this series.

Next up is the Presenter. As i mentioned in the previous post, this class is a bit of a coordinator between the user, the View and the Model. That means it interacts with both the View and the Model. It can interact with its View directly, which is still done through an interface to enable easy testability, or with other Views' Presenter indirectly. For this indirect communication between Presenters, we use Event Aggregation through an Event Aggregator. I've covered this before, so i'm just going to link to my old post about it. In the sample that accompanies this series, you'll find the code for the Event Aggregator and since it's also shown in the post i just linked to, there's no need to show it in this post again. Just keep in mind that each Presenter will automatically have a reference to the Event Aggregator.

Another thing that each Presenter needs to have is a reference to a factory which creates proxies to communicate with the Model (Service Layer). I'm using Agatha's IAsyncRequestDispatcherFactory for this since i believe it's the most optimal and clean way to communicate with a WCF Service Layer, especially when doing Silverlight, provided of course that the Service Layer is also implemented with Agatha. Now, since i'm the author of the Agatha project i'm probably (duh) a bit biased but check out the Agatha project and decide for yourself whether this is a good choice or not.

Having said all that, we can now take a look at the implementation of the base Presenter class:

    public abstract class Presenter<TView, TBindingModel>
        where TView : IView
        where TBindingModel : BindingModel<TBindingModel>, new()
    {
        protected Presenter(TView view, IEventAggregator eventAggregator, IAsyncRequestDispatcherFactory requestDispatcherFactory)
        {
            View = view;
            EventAggregator = eventAggregator;
            RequestDispatcherFactory = requestDispatcherFactory;
            BindingModel = new TBindingModel();
        }
 
        protected IEventAggregator EventAggregator { get; private set; }
        protected IAsyncRequestDispatcherFactory RequestDispatcherFactory { get; private set; }
        protected TView View { get; private set; }
 
        public TBindingModel BindingModel { get; private set; }
 
        public virtual void Initialize() {}
 
        protected void PublishRemoteException(ExceptionInfo exceptionInfo)
        {
            EventAggregator.Publish(new RemoteExceptionOccurredEvent(exceptionInfo));
        }
    }

As you can see, there's not really much to say about this. The Presenter has its View, IEventAggregator and IAsyncRequestDispatcherFactory dependencies injected in the constructor and it automatically instantiates its BindingModel. The dependencies are made available to the derived classes (your actual Presenters) through protected properties. The Initialize method is something that you can optionally implement and will be called by the View when it has received its reference to the Presenter. There's also a protected utility method called PublishRemoteException which publishes a RemoteExceptionOccurredEvent through the Event Aggregator. This method can be used (but doesn't have to be) as the fallback whenever a service call fails. The idea is that something else is subscribed to the RemoteExceptionOccurredEvent with the Event Aggregator and that it can display these error messages in a uniform manner (or log them, or whatever). That's it as far as the base Presenter implementation goes.

Finally, we get to the View. We have the following base IView interface which the View class will implement:

    public interface IView : IDisposable
    {
        void Hide();
        void Show();
    }

As you can see, the IView interface inherits from the IDisposable interface. Many people think i go overboard with using the IDisposable interface, but i still think it's very important to deal with .NET's memory management efficiently, and especially in the case of Silverlight where we have observed numerous memory leaks in core UserControls due to, well, bad programming practices.

In this particular implementation of MVP, you are required to resolve the Presenter manually in your View code. I really would've preferred that this would be done automatically, but a Silverlight User Control can't inherit from a generic base class (where the generic parameter would be the type of the Presenter) because that introduces problems with both the Visual Studio designer as well as Blend. Another possibility would've been for the IOC container to instantiate the View, pass it to the Presenter since it's a constructor dependency and then let the Presenter pass itself to the View, but then you lose the ability to simply use your User Controls in the XAML of other User Controls. So for those reasons, the View is not instantiated by the IOC container, and you are required to resolve your own Presenter reference in your View. I know it's not exactly a best practice when it comes to Dependency Injection and using an Inversion Of Control container, but then again, we shouldn't sacrifice usability in order to achieve a theoretically technically cleaner solution either. So, without further ado, here's the base View class:

    public class View : UserControl, IView
    {
        private dynamic presenter;
 
        private static readonly bool inDesignMode =
            (null == Application.Current) || Application.Current.GetType() == typeof(Application);
 
        protected TPresenter CreateAndInitializePresenter<TPresenter>()
        {
            if (inDesignMode)
            {
                return default(TPresenter);
            }
 
            presenter = IoC.Container.Resolve<TPresenter>(new Dictionary<string, object> { { "view", this } });
            presenter.Initialize();
            DataContext = presenter.BindingModel;
            return presenter;
        }
 
        public void Hide()
        {
            Visibility = Visibility.Collapsed;
        }
 
        public void Show()
        {
            Visibility = Visibility.Visible;
        }
 
        public void Dispose()
        {
            // naive implementation of Dispose, but then again, this is just a sample
            IoC.Container.Release(presenter);
            CleanUpChildrenOf(this);
        }
 
        private void CleanUpChildrenOf(object obj)
        {
            var dependencyObject = obj as DependencyObject;
 
            if (dependencyObject != null)
            {
                var count = VisualTreeHelper.GetChildrenCount(dependencyObject);
 
                for (int i = 0; i < count; i++)
                {
                    var child = VisualTreeHelper.GetChild(dependencyObject, i);
 
                    if (child != null)
                    {
                        DisposeIfDisposable(child);
                        StopIfProgressBar(child);
                        CleanUpChildrenOf(child);
                    }
                }
            }
        }
 
        private static void DisposeIfDisposable(DependencyObject child)
        {
            var disposable = child as IDisposable;
            if (disposable != null) disposable.Dispose();
        }
 
        private static void StopIfProgressBar(DependencyObject child)
        {
            var progressBar = child as ProgressBar;
            if (progressBar != null) progressBar.IsIndeterminate = false;
        }
    }

First of all, you might notice that i'm storing a dynamic reference to the Presenter instead of a typed reference. I can't use a typed reference because i have no way to define the actual Presenter type parameter without causing problems with either Visual Studio's XAML designer, or Blend. Now, i could've introduced a non-generic base Presenter class which defines the Initialize method and a non-typed BindingModel property. But then i'd just be introducing more code solely for the purpose of paying lip service to the compiler. If you have a problem with the usage of the dynamic keyword, feel free to waste some time adding code that's not going to offer you any real benefit whatsoever.

As you can see, the CreateAndInitializePresenter method will resolve the Presenter through the IOC container (Castle Windsor in this sample) and i'm using a feature of the container which allows me to provide one of the dependencies myself (in this case, the View instance). There's another way to pass in the instance of the View with an anonymous type, but that didn't work with Windsor in Silverlight. After the Presenter has been resolved through the container, we call its Initialize method and we set the DataContext of our UserControl to the BindingModel instance of the Presenter. In the (naive) Dispose implementation, we release the Presenter instance through the container and we'll go through all of the children of this User Control in the Visual Tree to dispose the ones that implement IDisposable (for instance, embedded UserControls where you're also using this MVP approach) and we also manually stop every ProgressBar control that we might have. The only reason we do that is because there is a memory leak in the ProgressBar control which may have been fixed in Silverlight 4, but i haven't checked if this is indeed the case.

And that is it. We have a base class for our BindingModels, we have a base class for our Presenters, and we have a base class for our Views. We can now start using these parts together very easily.

In the next post, i'll describe the Sample project that accompanies this series (and yes, you'll finally be able to download it and check out all of the code on your own) and after that, we'll explore how we can develop User Controls with this approach.

MVP In Silverlight/WPF: Architectural Overview

15 commentsWritten on August 1st, 2010 by
Categories: MVP In Silverlight/WPF

Note: This post is part of a series. You can find the introduction and overview of the series here.

Just a little warning up front: I'm not going to show a diagram of the architecture. When it comes to this kind of posts, people often just scroll until they see a diagram which depicts the architecture, glance over it, either think they get it or won't get it, and base their opinions on just that. I want people to actually focus and read what i'm saying about this, so i'm not using any diagrams. This approach usually results in increased understanding of the architecture and less misunderstandings. Obviously, it's not a foolproof approach as you'll likely soon discover in the comments.

The MVP (Model-View-Presenter) pattern is an MVC-derivative pattern. The Presenter part is often referred to as a controller and its responsibilities differ between the two most known variants (more on that in just a little bit) of MVP. But the presenter is actually very comparable to the Controller in MVC. The biggest difference, in my opinion, between MVP and MVC is the following: In MVC, every user-initiated action is handled directly by the controller. In MVP, every user-initiated action is handled by the View, who then delegates this to the Presenter (or Controller in many implementations). That's why you often see MVC being used in web applications (where most MVC frameworks turn a click of a button into a direct method call on a Controller) and MVP in rich clients (where a button's Click event handler calls a method on the Presenter/Controller).

As if the difference between MVC and MVP weren't small enough, MVP is actually split up in 2 variants to add more confusion to the whole. One of them is the Passive View, and the other is the Supervising Controller. Simply put, in the Passive View variant the View is only responsible for visualizing data and delegating user input to the presenter. All logic that is required to control the View (including View-update behavior) and interact with the Model is put in the Presenter/Controller. In the Supervising Controller variant, the View is responsible for visualizing data, delegating user input, as well as View-update behavior. That means that the View will update itself when data is given to it, instead of having the Presenter/Controller take care of that. If you haven't made the link yet, the location of that View-update behavior of the Supervising Controller variant of MVP fits perfectly with Silverlight/WPF's data binding features (more on that later).

Now, i can imagine that the first 3 paragraphs of this post were pretty confusing with all these details about these patterns and their variations. But hey, blame Martin Fowler for that one. I'd like to avoid any future confusion with regards to this approach so i want to go over each part of this client-side architecture to make sure that you fully know what each part is responsible for.

In most (if not all) Silverlight applications, the Model will actually be a Service Layer that is hosted on an application server. Behind this Service Layer, you'll find either a rich Domain Model with behavior, or some representation of your Data Model and some other way to access the functionality that you need from your client. In the case of WPF applications, your Model is either a service layer as well, or it might actually be used directly in the case of a fat client. Whether it's behind a Service Layer or not, the Model contains and exposes (some of) the actual business logic of your system/application.

The View is responsible for visualizing the data that it needs to show, and to capture user-initiated actions (both in the form of data modification as well as clicks on user controls or other typical UI actions) so they can be delegated to the Presenter. That's all it should do. It makes use of data binding capabilities where it makes sense, and the only logic that it contains is to delegate user-initiated actions to the presenter, or to do something view-specific which can't be done through data binding (for instance: selecting the correct item in a TreeView). I know many MVVM evangelists advocate no code at all in the View's code behind, but there is a limit to how much logic you can pull out of the View while still providing more benefits than drawbacks. Initiating actions on the Presenter and interacting with actual UserControls is something that you can safely leave in the View, since pulling that kind of stuff out of the View hardly ever introduces actual benefits and is more often done to serve purely theoretical benefits, and it's just not worth the trouble.

The Presenter is basically the coordinator between the user, the View and the Model. Before the user can initiate an action or modify data, it needs to see either that data and/or a UserControl which could trigger that action. As mentioned earlier, visualizing data or UserControls is the responsibility of the View. The Presenter needs to retrieve that data from the model before it can be shown in the View, and it can also decide which actions can or can not be executed by the user (according to the user's permissions for instance, or according to the context of the current workflow, or a combination of both). When a user initiates an action (for instance, persisting modified data in the View), the Presenter needs to interact with the Model to complete the User's requested action.

At this point, you might be wondering: what exactly is the big difference between the Presenter and the ViewModel in the MVVM approach? Well, the answer to that is an extra part which i haven't talked about in this post yet. As i'm sure you all know, the ViewModel in the MVVM approach also takes care of everything that is needed to make good use of data binding. Silverlight and WPF have some very strong data binding capabilities and you'd be a fool not to use them. I know there are quite a few people who dislike data binding (especially when it's string-based) but in this case, the benefits definitely outweigh the drawbacks, by a very large margin even. So whichever client-side architecture you choose to use, it would be wise to make sure that it supports Silverlight/WPF's data binding features to the fullest. In fact, i suppose that's one of the biggest reasons why the MVVM pattern has taken off the way it did. It fully supports and encourages using the data binding features.

But, as we all know, with great power comes great responsibility. Data binding makes a lot of stuff easy to do. It removes a lot of repetitive, error-prone code that we'd either write manually every single time, or have generated by some tool/plugin. But if you use it incorrectly, data binding might cause unexpected method calls or accessing of properties. In the worst cases, this could result in unnecessary expensive operations being performed without you realizing it (at first). And i don't think i'm going out on a limb here by claiming that quite a few people have gotten bitten by this, no matter how good or bad you are as a developer.

From a performance point of view, you ideally want to make optimal use of Silverlight/WPF's data binding features, without risking unexpected expensive operations. From a code quality and design point of view, you might agree with me that facilitating data binding is a responsibility that should be shouldered by a dedicated class. With that, i mean a class which only takes care of everything that is related to data binding. And that is the part of this architecture i haven't discussed yet: the BindingModel (which i used to refer to as some slimmed down version of a PresentationModel, but that only caused more confusion).

The BindingModel is a class which is used by both the Presenter and the View. The Presenter puts data from the Model in the BindingModel. The View in turn binds to the BindingModel. If a user modifies that data, those modifications are immediately applied in the BindingModel because of Silverlight/WPF's two-way binding. If required/wanted/preferred, the BindingModel can perform simple client-side validation to the modified data. If the user then initiates an action, the Presenter will use the data in the BindingModel to interact with the Model. The BindingModel however will never interact with the Model directly.

And that is the big difference between this MVP approach and the MVVM approach. Data binding and interacting with the model are strictly separated, which makes sense on multiple levels. For one, this approach results in a better Separation Of Concerns (interaction with the model vs facilitating data binding). But it also makes sure that unexpected data binding events can never lead to unexpected expensive and unwanted interaction with the Model.

In the next post, we'll go over the infrastructure bits you'll need to work with this approach.

MVP In Silverlight/WPF Series

6 commentsWritten on August 1st, 2010 by
Categories: MVP In Silverlight/WPF

I recently criticized the MVVM pattern which pretty much every Silverlight and WPF developer has probably used by now. Reactions to that post were (as was to be expected) pretty varied. Quite a few people agreed with my statements. Others needed to see code to get a better idea of what i'm talking about. Others flat-out considered it (and my opinions in general in some cases) to be nonsense. Challenging the MSDN-recommended-way-of-development always seems to stir up emotions with a large group of .NET developers, but the fact of the matter is that it simply needs to be done if you think you've got a better alternative. Whether or not i'm actually right about it doesn't even matter. The whole point is that you should be aware of alternatives and that the approach you choose to follow is the result of an informed decision.

And that's why i decided to write this series instead of simply trying to back up my statements with a post that showed some code. It's pretty hard to back up architectural preferences with a little bit of code in a blog post. People will either complain that the example is too contrived, or that your example doesn't really illustrate the benefits of your architectural ideas and that it can be done much simpler. With this series, and its accompanying sample project (which i'll link to in a future post in this series), i hope to convince at least a few of you that the MVP approach can indeed be a much better choice over MVVM. I'm fully aware of the fact that plenty of 'typical' .NET developers will still criticize this series, the sample project and the approach that i'm advocating. And that's ok, really. We can all have our opinions and we can all develop our software the way we want to. And while i hope to 'convert' at least some of you, i'll already consider the whole thing a 'win' if i can just get a bunch of people to at least think about some of the things i'll talk about in this series.

These are the posts the series consists of:

  1. Architectural Overview
  2. Some Infrastructure Bits
  3. The Sample
  4. Implementing The Overview UserControl
  5. Implementing The Details UserControl
  6. Automated Tests
  7. Conclusions