I'm re-working a Winforms application and would like to employ a variation of the Presentation Model pattern for the UI. Could someone tell me from the following explanations if I'm doing it correctly?
I have decided to set up dependencies as follows:
Model <---- Presentation Model <---- View
That is:
The model is not aware of anything except itself.
The presentation model has a reference to the model (but not vice versa).
The view has a referenc开发者_StackOverflow社区e to the presentation model (but not vice versa).
I am using Winforms data binding to keep the view and the presentation model synchronised.
Now this all works like a charm, except when I need to deal with e.g. a click on a form's "Close" button. Since the presentation model has no reference to the view, it cannot subscribe to any events published by the view. Thus I've come up with the following crutch:
Presentation Model View
+--+ +--+
| | | |
| | | <--------X closeButton.Click event fires
| | | |
| | +--------X |
| | CloseRequested = true | | |
| | +--------> |
| | | |
| | CloseRequested CloseRequested | |
| <-----------------------------------< |
| | | |
| X--------+ | |
| | | IsClosed = true | |
| <--------+ | |
| | | |
| | IsClosed MustClose | |
| >-----------------------------------> |
| | | |
| | | X--------> view.Close()
| | | |
+--+ +--+
That is:
The user clicks the "Close" button.
The button's
Click
event is captured in the view, which reacts by setting the propertyCloseRequested
.Data binding transfers this value to a corresponding property in the presentation model.
The presentation model reacts to this change by setting its property
IsClosed
.Data binding transfers this value into the view's
MustClose
.The view reacts to this change by closing itself.
The presentation model is quite nicely decoupled from the view, and vice versa, however this is a lot of work only to process a single button command. Is there an easier way, given the dependency graph I've decided on?
I've recently been converting a Windows Forms application to the MVP architecture, and it looks like you've set up your dependencies in a similar way to what I've been doing. However, I simply have an IPresenter
interface which defines methods to allow the view to pass on user requests. As the view already has a dependency on the presenter and a reference to it, it seems sensible to simply call request methods on it directly.
So in my system, the presenter listens to events from the model and fires its own presentation events for any interested view to listen out for. The view responds to those events by updating itself as appropriate, and forwards user requests to the presenter when they are made.
it is only my opinion.
Working with presentation model require 100% UI support for data binding. Even WPF don't make the CLOSE action as Bindable. A lot of thing will not working smoothly in presentation model such as MessageBox Confirmation. even it can be abstracted with Presenter interface but still doesn't taste good and simplicity is sacrificed.
in the other hand, the main purposes of presentation model is to Test The View Logic. In some cases if your "Close Action" should be unit tested because of there is some logic before it is close then your code is the only choice. but if it is only a simple Confirmation "Are you sure you want to quit" then you better put that on the View not in presentation model because it is not require to unit test.
The view has a reference to the presentation model (but not vice versa).
AFAIK the presentation should have a refference to view more exactly to interface IView so that the presentation dosen't couple with concrete view. Then in presentation class you may call view methods and subscribe to view events via IView.
精彩评论