As the ViewModel has the job to "prepare" the Model's properties to get displayed in the View, what is the best way of referring to the underlying Models properties from the ViewModel?
I could think about two solutions by now:
Option 1 – Duplicate the Model's properties in the ViewModel (wrapper-approach)
Architecture
class Model
{
public string p1 { get; set; }
public int p2 { get; set; }
}
class ViewModel : INotifyPropertyChanged
{
// Model-instance for this ViewModel
private Model M;
public string p1
{
get { return M.p1; }
set
{
M.p1 = value;
// assuming View controls are bound to the ViewModel's properties
RaisePropertyChanged("p1");
}
}
// let's say, I only want to check a Checkbox in the View,
// if the value of p2 exceeds 10.
// Raising the property changed notification would get handled
// in the modifying code instead of the missing setter of this property.
public bool p2
{
get
{
if (M.p2 > 10)
{ return true; }
else
{ return false; }
}
}
// Initialize the Model of the ViewModel instance in its c'tor
public ViewModel()
{ M = new Model(); }
}
Binding
<Textbox Text="{Binding p1}"/>
<Checkbox IsEnabled="False" IsChecked="{Binding p2, Mode=OneWay}"/>
Advantages
- Full control about how the Model's properties are displayed on the View as shown in p2: int gets converted to bool on demand.
- Changes of the properties of the ViewModel could be raised individual, might be a little performance increase compared to option 2.
Disadvantages
- Violation of DRY.
- More Code to write/maintain.
- Modifications to the Model/ViewModel could easily become shotgun surgery.
Option 2 – Treat the whole Model as property of the ViewModel
Architecture
class Model
{
public string p1 { get; set; }
public int p2 { get; set; }
}
class ViewModel : INotifyPropertyChanged
{
// Model instance for this ViewModel (private field with public property)
private Model _M;
public Model M
{
get { return _M; }
set
{
_M = value;
// Raising the changing notification for the WHOLE Model-instance.
// This should cause ALL bound View-controls to update their values,
// even if only a single property actually got changed
RaisePropertyChanged("M");
}
}
// Initialize the Model of the ViewModel instance in its ctor
public ViewModel()
{ M = new Model(); }
}
Binding
<Textbox Text="{Binding M.p1}"/>
<Checkbox IsEnabled="False" IsChecked="{Binding M.p2, Mode=OneWay, Converter={StaticResource InverseBooleanConverter}"/>
Advantages
- Can save a lot of code.
- Reduces complexity.
- Increases maintainability.
Disadvantages
- In this approach, the ViewModel is nothing more than a continuous-flow water heater for the Models properties, except for some possible interaction logic for the View.
- No control about how the Model's properties are displayed in the View – which ultimately leads to total needlessness of the ViewModel and implementation of conversion logic in the View.
Best Answer
It is the responsibility of your ViewModel to expose the Model to the View, you should not expose the Model's properties as additional properties in the ViewModel, instead, your View should bind directly to the model.
Additionally, it isn't wrong to have logic in your Model, in fact, it makes more sense to contain model related code within the model, as opposed to the ViewModel.
Here is an example:
So to answer your question a little more directly, you should expose your model in the view model as a property.
Therefore, your View will bind to the
Model
property, like you have already done so.EDIT
In the example for casting to the type, you can implement a read-only property in your Model, like so:
Now the magic here would be that you will need to call the
INotifyPropertyChanged
for this property wheneverMyInt
changes. So your other property would look something like this: