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 businessObject
s 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:
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:
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.
CodeProject