I'm making the move from MVP to MVVM, and a little confused as to how best bind the ViewModel
to the Model
. I understand how we can leverage WPF's data binding infrastructure to route events between the View
and ViewModel
using ICommand
and INotifyPropertyChanged
interface, e.g., the View
:
public class MyView
{
public MyView()
{
InitializeComponent();
DataContext = new MyViewModel();
}
}
and the ViewModel
:
public class MyViewModel : INotifyPropertyChanged
{
public MyViewModel(){}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public ICommand MyCommand ...
}
This works great!
Now, typically with MVP I'd have my Presenter
hold a reference to the Model
via constructor injection, and raise events on the Model
from the Presenter
to update data in the Model
. I tried the same approach with MVVM, but this requires the ViewModel
to take the Model
as a dependency in its constructor, which seems to make things a little messy with MVVM when using it straight out of the box without some form of IOC (with WPF at least).
So, my two questions are:
Model
into the ViewModel
the right approach, or should I be implementing INotifyPropertyChanged
interface on the Model
and making use of WPF's binding infrastructure? Now to bind the ViewModel(TaskViewModel in our case) and View(MainWindow. xaml) we have to write the below code. This is the code present in the MainWindow() constructor. The above code is setting the DataContext of the MainWindow as instance of the TaskViewModel.
It is the "pure" MVVM approach: the View
must depend only on the ViewModel
. The ViewModel
itself is a bridge between the View
and Model
.
The motivation — definition and responsibilities of the Model
, View
and ViewModel
and also their relationships:
- The Model, which provides a view-independent representation of your business entities. The design of the model is optimized for the logical relationships and operations between your business entities, regardless of how the data is presented in the user interface.
- The View class which is the user interface. It displays information to the user and fires events in response to user interactions.
- The ViewModel class, which is the bridge between the view and the model. Each View class has a corresponding ViewModel class. The ViewModel retrieves data from the Model and manipulates it into the format required by the View. It notifies the View if the underlying data in the model is changed, and it updates the data in the Model in response to UI events from the View.
-- Implementing the Model-View-ViewModel Pattern, MSDN.
Conclusion. Injecting the Model
into the ViewModel
seems to be the right approach. Also, instead of injecting Model
it can be useful to inject:
Model Factory
to create the Model
— lazy initialization;Service
(Service Facade
) to retrieve the Model
— lazy loading.As shown in the "MVVM Unleashed" book by Michael Brown, the following MVVM's potential benefits can be leveraged: maintainability, testability, "blendability", portability. At least, dependency injection (in the described case by using dependency injection container) allows a design to follow the Dependency Inversion Principle:
The principle of dependency inversion is at the root of many of the benefits claimed for object-oriented technology. Its proper application is necessary for the creation of reusable frameworks. It is also critically important for the construction of code that is resilient to change. And, since the abstractions and details are all isolated from each other, the code is much easier to maintain.
-- The Dependency Inversion Principle, Robert C. Martin, 1996.
As a result, such MVVM's benefits as the maintainability and testability seem to be improved when the Dependency Inversion Principle is followed. Dependency injection container is just a tool to follow the Principle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With