We are working with the MVP pattern, and I was wondering how to deal with GUI actions.
For instance, when the user wants to delete a row from a grid, the user presses the delete button. At this point you can do two things:
1) Call _presenter.DeleteRow() and the presenter then calls _view.SelectedRow. Then the presenter calls view.AskUserForConfirmation(), and when it gets back DialogResult.OK, the presenter actually deletes the underlying object and refreshes the grid.
2) The form asks the user for confirmation and when the DialogResult is OK, then presenter.Delete(myObject) is called OR presenter.Delete() is called and within the Delete method the object is retrieved by calling _view.SelectedRow.
How do you handle these kinds of situations?
The MVP Pattern is supposed to separate your logic, view, and data access. So when trying to decide where something should go, ask yourself if there is actual business logic in what you're trying to do.
Would you want your business layer to have logic about displaying a pop up window? Probably not. It is just a confirmation message. You may want to have a helper class that generates your stylized pop up window, but that is seperate from your Presenter layer.
Option 2. Asking for confirmation is a UI responsibility that the presenter shouldn't need to worry about. I don't involve the presenter until it's time to actually do something to the model, or until some complex business logic needs to be invoked.
This doesn't mean option 1 is invalid. It just creates unnecessary view/presenter chatter, in my opinion.
Related
I am creating a new winforms application that will have datagridviews which will load matrix data, and I want the user to be able to do a bunch of operations on the data, like showing/hiding columns, editing cell values, and filtering too.
I thought of using the MVP pattern (Model, View, Presenter).
I wanted to create a presenter class, which would handle all the logic (meaning any events that the user triggers), eventually end up in the presenter which will work on the raw data (the matrices). This seems logical up to now but my question is what do I do if I want to pass the controls themselves (like the datagridviews)? Should these controls be sent the presenter class or is that bad design?
Perhaps it's better to find ways to only modify the raw data and then update my datagridviews?
It is not a good idea to pass around controls. If you're going to use a pattern such as "MVP", then you should have the "model" contain the representation of the "view". In this case if there are various details pertaining to a set of data it belongs in the model. Then you pass the model around.
Perhaps it's better to find ways to only modify the raw data and then update my datagridviews?
So, to answer this question, "yes". Use the model to wrap the data and pass it around.
Update
Specifically, with WinForms controls belong to containers, being that they are reference types and have lots of exposed events you run a HUGE risk of passing a reference from one Form to another Form. Now, imagine that the first Form is done being used and closes and disposes, it kills the reference to the control and attempts to unwire events. Do you see where I'm going with this? It quickly becomes a nightmare trying to correctly cleanup references, and un wire event handler and since controls belong to one container by design it breaks that paradigm.
It's better to have a separation of concerns. If you need a view to have certain data, it's always best to pass around the data itself...
I'm learning Silverlight/MVVM. Now I'm facing problem with Commands, that I think are just overcomplicated. I wanted to execute close on child window after command.
According to separation of concers it should be execute from view, as I understand.
As far as I looked for solution I found it and it wasn't trivial for such a trivial task.
To sum it up, I must say that separation of view, viewmodel and model are great ideas.
Also Binding from View to ViewModel is nice and clean.
But what about Commands. As I understand they are just piece of code to execute (like delegates).But they are too complicated and troublesome.
I want to know you opinion. What about idea that VieModel would have properties and normal public methods, that it will be executed from events of views. If I will not pass any view related element to the view model it still will be MVVM, right?
Of course, there will be one drawback, that i will have to bind separatly IsEnabled to properties in ViewModel to mimic CanUpdate functionality of Commands. It's not that you view doesn't know about ViewModel.
Views are not very testable, are they?
It would be very flexible. For example, in event for click i would do some strict view logic, call method from viewmodel object and then maybe call another method and after all that do some more view logic.
So, what do you think?
You can try using Cailburn.Micro. It is an open-source framework that runs over WPF and hides some of it complexities. For example, it replaces command-classes with just plain method calls.
You can implement windows-closing by returning a special result that will do the actual closing of the view. That way your ViewModel will still be fully unit-testable, as you can check that expected result is returned, and it will not be view-aware.
Here is an example on how to implement this: https://stackoverflow.com/a/10175228/258737
Events occur in our Model and ViewModel that necessitate creating the appropriate View. The question is how to do this and avoid having any View code in the VM or M?
Here's the sequence of events so you can see this dilemma:
The user sets a number fields in a form to start a long running background process and then clicks the "Start" button. If this long running process succeeds then it needs to popup a chart with graphs to show the results. However, if the data fails processing for any reason then it can't popup charts, instead it logs an error message which is show in the a text box on the form.
Right now, that start button calls a method in the ViewModel which actually starts the background thread.
Only the background can determine when or if to create the view.
Currently we have this working by using an interface called ChartInterface. The view implements this interface and then sets a callback delegate all the way down to the backend model. When it decides to create the Chart it invokes the callback and uses the interface to pass the appropriate data and such.
However, this presents a problem because it can potentially produce dozens or hundreds of charts. So we need to have a "Dashboard" with a list of all the charts for the user to select which one to see.
So now the backend needs to decide when or if to create the Dashboard View, then add Chart View to it.
So it's getting messier because there will be increasingly more of these situations as we have lots of Models that need views so creating tons of callback delegates gets ugly fast.
An idea that seems to simplify instead of lots of callbacks will be to only pass an interface to a ViewBinder to the backend. Then each time it creates a model object, it can pass it to the ViewBinder to see if it wants to bind any view object to it.
Our thinking is that most any of the backend objects will be interesting (eventually) to monitor graphically. So if everyone of them after contructing is passed to the ViewBinder interface, then the view can decide if it wants to bind anything to it.
This is sounding better all the time.
The answer became clear while working on the code.
public interface ModelBinderInterface {
void TryBind( object model);
}
instead of one global "server locator" it's more natural for EVERY view object to implement this interface.
Then when it creates any ViewModel objects it assigns itself to the ModelBinder property of the the viewModel object.
Now the ViewModel can pass this same interface to the back end process.
When ever any relevant model gets instantiated, then it calls the ModelBinder with the object.
Then the View object can decide if it can instantiate the object, if not, it can pass the call up to it's parent which also implements ModelBinderInterface.
This way each view can handle instantiating views that it understand whether that be adding a control to a DataGridView or binding the object to a ListView, etc.
Of course, this still allows for a singleton ModelBinder because the lower levels can keep handing the call up to the top level application ModelBinder which there's only one and it can offer singleton instances.
I have implemented the MVP pattern (passive view) in my C# Forms application.
In my case the model is a motor controller laser system, where the model actually is like a facade of two other models (one the motor control system, the other the laser system).
My presenter is a mediator of model-events and methods to the view which handles the user interface.
Suppose my view has a setting for the laser power. The user sets this to some value, which gets sent to the presenter, which in turn send the request to the model.
If the laser power is out of range my model throws an error which get catched by my presenter.
How do I best mediate this message to the user?
I thought about making, in my view, a method; HandleError(string message), and invoke this from the presenter.
This is my first project using MVP, so I haven't got the experience to say which way is the best way.
In the view, create a property for an Error Message. From the presenter you can set the value of this property. Back in the view on the setter for the property, store the value that's set as any typical property would do, but in addition add your logic for whatever the user interface needs to do. The View can then control the flow of what happens within itself.
I am trying to implement the MVP pattern for WINFORMS. Its a simple for with a button and a Grid, on button click, the grid will load, and user can fill in values into the grid.
For my button click event, I have something like this:
_presenter.LoadGrid();
Which is simple and straightforward.
My question is, in regards to grid...
I am planning to have a row click event firing....for enabling/disabling the subsequent input fields for the specific columns/rows of the grid etc.
I understand that the presenter should not contain any GUI elements and the View(form) shouldn't really contain Logic?
So, to have that GridRowClick event firing, I need to manipulate the grid (GUI) based on business rules (Logic). I am lost between letting the presenter handle the logic of that click event or the form?
If the presenter is to handle the click event, wont that include the gui components?
If the view is to handle the click event, the fieldnames etc are all business driven(logic), dynamically binded based on datatable returned from the business layer.
Any advice will be much appreciated.
Cheers
There are (at least) two variants of MVP.
Passive View Pattern
Supervising Controller Pattern
Passive View, as its name suggests, treats the UI as a more or less passive interface between the user and the application. It moves as much testable code to the presenter as possible leaving the view to handle only the most basic UI updates.
Supervising controller gives the view a little more responsibility by letting it handle data synchronization. This is usually done through data binding.
In either case event handling is accomplished by delegating to a presenter method:
EventHandler()
{
presenter.HandleEvent();
}
If handling the event requires making changes to the form, you expose what needs to be updated as a property:
public string PropertyThatNeedsToBeUpdated
{
get
{
return Control.Property;
}
set
{
Control.Property = value;
}
}
For Passive View, grids are a hurdle. Their complexity make it cumbersome to capture all the possible events. With Supervising controller, grids are much easier since you leave data synchronization up to the data bound controls.
You have to make the judgment call as to which is more appropriate for your situation.
The key is getting all that business logic into the presenter where it's testable.
The view should call the presenter to perform the business logic, passing the information needed (e.g. the data associated with the clicked row).
The presenter then performs the business logic and updates the data.
Depending on what type of changes you need to make, that might be all you need to do, since the existing data binding might be sufficient to update the view automatically. If it isn't sufficient, the presenter can make one or more calls to the view (via its interface of course) in order to make the required changes.
As you say, you should aim to minimize the amount of non-trivial code in your view, and in particular, the view shouldn't have any business logic in it.
EDIT:
Some good general information on MVP and other presentation patterns here: http://martinfowler.com/eaaDev/uiArchs.html
You might want to check out Part 4 of the video series from Polymorphic Podcast. He uses the supervising controller pattern and shows a technique for handling data grids. The whole series was actually a good introduction for me.
http://polymorphicpodcast.com/shows/mv-patterns/