Click here to Skip to main content
15,867,906 members
Articles / Desktop Programming / WPF

MVVM - Creating ViewModel: Wrap your business object (Solution 1 of n)

Rate me:
Please Sign up or sign in to vote.
4.00/5 (3 votes)
25 Feb 2010Ms-PL2 min read 23.3K   10   2
When you create WPF applications, you may (or you should !) use the M-V-VM pattern and so have to use/create ViewModel.The viewModel job is mainly to expose properties of your businessObjects to your views, ready for binding. Here is a first solution to create ViewModel from your model.

Introduction

When you create WPF applications, you may (or you should!) use the M-V-VM pattern and so have to use/create ViewModel. The viewModel job is mainly to expose properties of your businessObjects to your views, ready for binding.

To be ready for the binding, the most used solution is to implement INotifyPropertyChanged and to fire events for every change made. An issue is that you often do not create the business object used by the application which are created by another team and that these objects are not ready for binding. So you must find a solution to creates an object which will in fact be very similar of your business object, BUT ready for binding.

In this series of posts, I will try to give some of the solutions we can use to do so.

Wrap your Business Object (Solution 1 of n)

The first solution which appears in every developer's brain is to wrap theBusinessObject(BO) into the viewmodel. Every property of your ViewModel will actually be some kind of proxy to/from the underlying BO.

For example, let's take for granted that you have a businessObject like this:

C#
/// <summary>
/// I'm the business object created by another team. 
/// I'm not binding-aware : shame on me !
/// </summary>
public class MyBusinessObject
{
  public String LastName { get; set; }
  public String FirstName { get; set; }
  public int Age { get; set; }
  public List<String> FriendsName { get; set; }
}

You will then give the Business object to your viewModel which will act as a proxy. The result will be something like this:

C#
public class ViewModelWrapped : ViewModelBase
{
private MyBusinessObject _myBusinessObject;
private ObservableCollection<String> _friendsName;
 
public ViewModelWrapped(MyBusinessObject myBusinessObject)
{
  _myBusinessObject = myBusinessObject;
  _friendsName = new ObservableCollection<string>(myBusinessObject.FriendsName);
}
 
public String FirstName
{
  get { return _myBusinessObject.FirstName; }
  set
  {
    FirePropertyChanged("FirstName");
    _myBusinessObject.FirstName = value;
  }
}
 
public String LastName
{
  get { return _myBusinessObject.LastName; }
  set
  {
    FirePropertyChanged("LastName");
    _myBusinessObject.LastName = value;
  }
}
 
public int Age
{
  get { return _myBusinessObject.Age; }
  set
  {
    FirePropertyChanged("Age");
    _myBusinessObject.Age = value;
  }
}
 
public ObservableCollection<String> FriendsName
{
  get { return _friendsName; }
  set
  {
    if (value != null)
    {
      FirePropertyChanged("FriendsName");
      _myBusinessObject.FriendsName = value.ToList<String>();
    }
  }
}
}

Notes: Something interesting to look at is how we wrap our collections to make them bindable: quite a job! More over the model and the viewModel list are no more synched... The list object itself is synched but the operation on the collection will be made on the viewModel collection and no more on the model collection. In this case, adding or removing a friend's name will affect only the ViewModel and not the model.

Pros and Cons

Pros:

  • The name of the properties exposed to your views can be different from those in the business object
  • It's very easy to understand the code when you read it again, even a few months later

Cons:

  • It's a very boring job to re-create the properties of the viewModel to map those from the BO
  • Collection and Set of the model are no more synched with the ViewModel
  • Copy-cut code can leads to error, especially when raising INotifyPropertyChanged events where case matters

N.B.: I've found an article of Josh Smith on this subject that you may find useful too.

Shout it kick it on DotNetKicks.com
This article was originally posted at http://blog.lexique-du-net.com/index.php

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer http://wpf-france.fr
France (Metropolitan) France (Metropolitan)
Jonathan creates software, mostly with C#,WPF and XAML.

He really likes to works on every Natural User Interfaces(NUI : multitouch, touchless, etc...) issues.



He is awarded Microsoft MVP in the "Client Application Development" section since 2011.


You can check out his WPF/C#/NUI/3D blog http://www.jonathanantoine.com.

He is also the creator of the WPF French community web site : http://wpf-france.fr.

Here is some videos of the projects he has already work on :

Comments and Discussions

 
QuestionHow to keep the collections synchronized Pin
dadge_791-Mar-10 23:15
dadge_791-Mar-10 23:15 
Hello,

You can easily keep the collection synchronize with your model using a "CollectionChanged" event on your ObservableCollection.

All you have to do is to modify your ViewModel constructor and add an handler :


public ViewModelWrapped(MyBusinessObject myBusinessObject)
		{
			_myBusinessObject = myBusinessObject;
			_friendsName = new ObservableCollection<string>(myBusinessObject.FriendsName);
			//add an event when the ObservableCollection changed to synchronize the model
			_friendsName.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(FriendsNameCollectionChanged);
		}

		void FriendsNameCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			//when items are added to the ObservableCollection, we add them to the model
			if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
				_myBusinessObject.FriendsName.AddRange(e.NewItems.OfType<string>());
			//when items are removed from the ObservableCollection, we remove them from the model
			if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
				_myBusinessObject.FriendsName.RemoveAll(s => e.OldItems.Contains(s));
		}

AnswerRe: How to keep the collections synchronized [modified] Pin
jmix901-Mar-10 23:20
jmix901-Mar-10 23:20 

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.