I've started to wrap my head around the whole MVP pattern and despite I'm doing fine with single objects it starts getting difficult when it comes to collections.
So let's say we're architecting a simple WinForms application that consists of a DataGrid within a Form, with the data Model being a simple collection of stuff, where such stuff has a bunch of properties and the View is going to actually display them:
Model
public class Person
{
public string Name { get; set; }
public DateTime Birth { get; set; }
public bool IsCool { get; set; }
}
public class People
{
public List<Person> Persons { get; set; }
}
View
public interface IPeopleView
{
List<People> ListOfPeople { get; set; }
}
public partial class PeopleViewImpl : Form, IPeopleView
{
private DataGridView _grid开发者_开发技巧 = new DataGridView();
public PeopleViewImpl()
{
InitializeComponent();
}
// Implementation of IPeopleView
public List<People> ListOfPeople
{
get { return /* TODO */; }
set { _grid.DataSource = value; }
}
}
Presenter
public class PeoplePresenter
{
private People _model;
private IPeopleView _view;
public PeoplePresenter(People model, IPeopleView view)
{
_model = model;
_view = view;
}
void UpdateView()
{
_view.ListOfPeople = _model.Peoples;
}
}
So what should I implement at View's List<People> ListOfPeople
getter as well as how should I invoke Presenter's UpdateView()
?
And generally, which extra Presenter methods would be interesting to have in order to achieve MVP Passive View and Supervising Controller respectively?
Any advice, code style review or opinion will be sincerely appreciated. Thanks much in advance.
First of all, you should decide for one pattern:
- Supervising Controller is appropriate if you want to leverage data binding and if a tool for automated view tests is available
- Passive View is indicated if your view data becomes more complex or if you have to rely on pure unit tests for the complete view
- Presentation Model (also known as Model View ViewModel) is ideal if you need easy access to the complete view state and if you have code generation available
I have collected all aspects as well as links to useful considerations and examples.
In either case, you should define a PeopleModel
and let PeopleViewImplementation
reference PeopleModel
. This clearly separates the model from the view.
When it comes to collections, Supervising Controller can rely on the data binding of a list to the DataGridView
. See winForms + DataGridView binding to a List. Only Passive View and Presentation Model require additional code for mapping the list to the view fields respectively to the Presentation Model.
Secondly, the data mapping should be clarified: Should PeopleView
show a list of persons or a list of several peoples? The DataGridView
can either display one person per row or one people per row. If one person is displayed per row, the treatment of the people could be achieved in one of the following ways, for example:
- Show all persons of one people on one page and add a pager element to navigate between different peoples
- Show all persons of one people in the data grid and add a selection widget for the people, e.g. a tree with all peoples
- Mix persons of different peoples in the data grid and add a column to display the people of each person
My suggestion is to have a ViewModel for that collection. The view implementation will have the responsibility of create new instances and update old, but it won't touch anything of your actual model. In order to retrieve them, just iterate the rows an create new. Finally, the presenter will iterate that collection and create/update each member of your model. (I also suggest using IEnumerable<> and using yield return so the collection is iterated only once).
For showing the data, you can also use this ViewModel (so it will be consistent) or just use the actual model (in a readonly fashion) if they are different for some reason (maybe yo show more information than what you can edit).
Hope it helps.
精彩评论