Click here to Skip to main content
15,868,016 members
Articles / Programming Languages / C#

MVVM – The ‘Other’ ViewModel

Rate me:
Please Sign up or sign in to vote.
4.00/5 (1 vote)
1 Dec 2010CPOL3 min read 16.9K   3   5
MVVM – The ‘Other’ ViewModel

Something that we regularly do at work is add additional properties to business objects that are only for use on the client (isDirty, HasChanged, …etc.). We have always just added these to the business object directly and thought nothing of it, but after listening to a Hanselminutes interview with Laurent Bugnion, I discovered the ‘other’ use for a ViewModel – wrapping client side business objects to expose new properties. This is also useful in removing the overhead of viewing objects via a converter.

I have recently started looking at ASP.NET MVC as well and the way to pass things between controller and view is by using a ViewModel class. This overload of the term had not translated into being useable in MVVM as well so what follows is a short, simple example of using a ViewModel to better model some data to fit a view.

Let's say we have a meeting object that we have extracted from a service and it is now ready to display on our client. This business object has no real relation to the ORM version of the same object if we are correctly differentiating between them and client facing business objects so it has no in-built tracking to determine if it has changed and we don’t want to send it back to the service for updating if nothing has changed. Our class looks like this:

C#
public class Meeting
{
    public Meeting()
    {

    }
    public string Subject { get; set; }
    public string Location { get; set; }
    public DateTime StartTime { get; set; }
    public List<Person> Attendees { get; set; }
}

This is a very simple class to define our meeting but it has no way of knowing if it has changed and also the StartTime property is stored on the server as UTC but the client could be anywhere.

Taking the latter problem first, you may be tempted to bind directly to the StartTime property of this object and use a converter to convert to the appropriate time zone based on the user culture (as I have done many times). As for the problem with a meeting change, there has to be some way of telling an object that it has changed. Both of these problems can be solved with a MeetingViewModel. This is a VM that follows the decorator pattern and could be implemented as follows:

C#
public class MeetingViewModel
    {
        private Meeting inner;
        public MeetingViewModel(Meeting m)
        {
            inner = m;
        }

        public Meeting Inner
        {
            get
            {
                return inner;
            }
        }

        public string Location
        {
            get
            {
                return inner.Location;
            }
            set
            {
                inner.Location = value;
            }
        }
        public DateTime StartTime
        {
            get
            {
                return inner.StartTime;
            }
            set
            {
                inner.StartTime = value;
            }
        }
        public List<Person> Attendees
        {
            get
            {
                return inner.Attendees;
            }
            set
            {
                inner.Attendees = value;
            }
        }

        public DateTime LocalStartTime
        {
            get
            {
                return inner.StartTime.ToLocalTime();
            }
            set
            {
                inner.StartTime = value.ToUniversalTime();
            }
        }

        public bool IsDirty { get; set; }
    }

Here, we now have a nice property that sorts out the StartTime into a local time for us and a property that determines if this object has changed. In your VM that controls your view, you now operate on an object of type MeetingViewModel and all bindings are to this object. When it comes time to save the object, you simply need to check if you have set the dirty flag and if so, extract the internal Meeting object using the get-only property and send it back to the service.

This is also a nice way of working with business objects that you have no control over such as from an external web service or third party library. Once you start to understand the power of this approach over simply using converters, you will find yourself writing VMs for all of your business objects that you need to modify slightly on the client side when you need properties like the above or other bits of information like calculated properties.


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I am a developer currently working for a financial company in the UK with a focus on back end work using NServiceBus. Personally I also enjoy working with ASP.NET (MVC), WPF, ruby and investigating best practice using methods like TDD and bettering the quality of code.

Comments and Discussions

 
QuestionDo you have a generator for your decorator? Pin
Dr. Jones DK9-Dec-10 23:15
professionalDr. Jones DK9-Dec-10 23:15 
AnswerRe: Do you have a generator for your decorator? Pin
Leom Burke10-Dec-10 0:25
Leom Burke10-Dec-10 0:25 
QuestionSetting the isDirty property Pin
golightlys6-Dec-10 6:29
golightlys6-Dec-10 6:29 
AnswerRe: Setting the isDirty property Pin
Leom Burke6-Dec-10 7:25
Leom Burke6-Dec-10 7:25 
GeneralRe: Setting the isDirty property Pin
golightlys6-Dec-10 7:48
golightlys6-Dec-10 7:48 
Cool. I can understand leaving out details to make the main point easier to understand. I just was worried that I was missing something with the MVVM pattern. It looks like I am not (at least not with regards to setting isDirty). Thank you for the article.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.