GUI Design Pattern , MVP, Tab Control
I have an application that has a window similar to the one bellow .
alt text http:开发者_如何学C//a.imageshack.us/img137/7481/screenshotxh.jpg
The requirement here is that when the user clicks the Save button everything has to get saved. The "Save" and "Reset" buttons are "common" to all tabs. Hence, when the "Personal Information" tab is selected and "Save" is clicked the program should also save changes made in the "Friends" tab and changes made in the "Employment History" tab.
The app already has code for the following and I want to keep this code:
-PersonalInformationView , PersonalInformationPresenter, PersonalInformationModel
-FriendsView, FriendsPresenter, FriendsModel
-EmploymentHistoryView, EmploymentHistoryPresenter, EmploymentHistoryModel
Each presenter has a Save method.
The question is what would be a good design pattern to use taking into consideration that I want to keep the code I already have. Also, I want this window to have model, view, presenter as well. Or maybe I should rephrase my question a bit: what's the best way of including "sub-views", "sub-presenters" when programming MVP ?
Regards, MadSeb
I personally would suggest making an abstract interface, ISaveable, or osmething and ensure that each of the presenters implement this, than go through each presenter as an object of ISaveable and save each one.
I would make your new presenter take in your sub presenters as constructor arguments, something like:
class DialogPresenter {
private readonly IDialogView view;
private readonly PersonalInformationPresenter personal;
private readonly FriendsPresenter friends;
private readonly EmploymentHistoryPresenter history;
void DialogPresenter(IDialogView view, PersonalInformationPresenter personal, FriendsPresenter friends, EmploymentHistoryPresenter history) {
this.view = view;
this.personal = personal;
this.friends = friends;
this.history = history;
}
bool Display() {
this.personal.Display();
this.friends.Display();
this.history.Display();
return this.view.Display() == DialogResult.Ok;
}
void Save() {
this.personal.Save();
this.friends.Save();
this.history.Save();
}
}
Of course, if your presenters had a common interface between them, this could be simplified (and made more extendable) like so:
class DialogPresenter {
private readonly IDialogView view;
private readonly IPresenters[] presenters;
void DialogPresenter(IDialogView view, IPresenters[] presenters)
{
this.view = view;
this.presenters = presenters;
}
bool Display() {
foreach (var item in this.presenters)
item.Display();
return this.view.Display() == DialogResult.Ok;
}
void Save() {
var validation = new List<string>();
foreach (var item in this.presenters)
validation.AddRange(item.Validate());
if (validation.Count > 0) {
_view.ShowErrors(validation);
return;
}
foreach (var item in this.presenters)
validation.AddRange(item.Save());
}
}
Edit: Calling code would be something like this:
void DisplayForm() {
using (var frm = new frmDisplay) {
//or just use DI to get the models etc
var personal = new PersonalInformationPresenter(personalModel, frm.PersonalTab); //some properties to expose your views
var friends = new FriendsPresenter(friendslModel, frm.FriendsTab);
var history = new EmploymentHistoryPresenter(employmentHistoryModel, frm.HistoryTab);
var presenter = new DialogPresenter(frm, personal, friends, history);
if (presenter.Display()) {
presenter.Save();
}
}
}
Hope that is of some inpsiration/help :)
My suggestion is to create ISaveableView with save method. Each of your views will implement the interface. I am guessing that your tabs implements the views you've described. When you click the save button you can cast the active tab to ISaveableView and call its save method
精彩评论