What is the best breakdown of responsibility when using a virtual grid and the MVP pattern in a winforms application.
including:
Getting callbacks from the grid on user changed cell updates
Callback from the grid to set the style and value of a cell given a row and column
The exact responsibilities in the many patterns that are referred to as Model-View-Presenter vary. Mainly they vary about how much control is exerted over the view by the presenter. Martin Fowler has an in depth discussion of a number of different variants in his chapter on GUI Architectures, it's well worth a read.
Have a look at Presenter First as it deals with adapters and the responsibilities in some depth.
Both Passive View and Supervising Controller are worth looking at.
model (or domain model) == logical representation of the entities involved in the system including their state and behaviour
presenter == listen for events from view (and maybe model) and service those requests, convert model types into view types (passive view), this is really plumbing to hide the view and the model from each other. Reacts to stimulus from the user.
view == presentation: the visual representation of the model that the user can interact with, collecting user input
Your specific questions around the callbacks and getting the grid cell style are both going to involve the view handling events from grid and raising events back to the presenter to request actions or retrieve data from the model. This is perfect for the callback when the cell content is updated (this needs to be published to the presenter so that the presenter can validate the change in the model and make the change in the model).
For the grid cell style I am thinking that some sort of adapter in the view may need to translate the state from the model (retrieved via an event from the view to the presenter) into the grid cell style information. This could happen in the presenter but I would personally prefer the presenter not to have knowledge of the widget in the view.
If I understand you correctly, the grid is part of the view implementation and is not visible to the presenter. In that case, the presenter should not need to know how the data is displayed, only how to provide them.
I would probably create a helper class, an adapter of some sort, which the grid communicates with. The grid sees nothing but this helper, ditto for the view.
The collaboration would be something like:
grid <-- helper <-- view <--> presenter
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have spent long time searching about MVVM in WPF. I understand why to use it. This is clear for me.
What I don't is, what is in ViewModel itself. I know it is the connection between the View and the Model. Also, I know (at least, what most of programmers suggest) that implement the INotifyPropertyChanged. Adding to this, the Commands.
Let say, that I have this Model (Code First with EF 6):
public class City
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CityId { get; set; }
[DataType("VarChar"), MaxLength(25), Required]
public string CityName { get; set; }
}
My Questions are:
1- In many examples I've seen, they recreate the same fields again in VM. What is the purpose, is it enough to have the whole object (City in my example). How about if there are many fields!.
2- To be able, to use it in my View (CRUD), how is the CityVm() will be in my example?.
I appreciate any help.
The view model in the MVVM pattern encapsulates the presentation logic and data for the view. It has no direct reference to the view or any knowledge about the view's specific implementation or type. The view model implements properties and commands to which the view can data bind and notifies the view of any state changes through change notification events. The properties and commands that the view model provides define the functionality to be offered by the UI, but the view determines how that functionality is to be rendered.
The view model is responsible for coordinating the view's interaction with any model classes that are required. Typically, there is a one-to many-relationship between the view model and the model classes. The view model may choose to expose model classes directly to the view so that controls in the view can data bind directly to them. In this case, the model classes will need to be designed to support data binding and the relevant change notification events.
The view model may convert or manipulate model data so that it can be easily consumed by the view. The view model may define additional properties to specifically support the view; these properties would not normally be part of (or cannot be added to) the model. For example, the view model may combine the value of two fields to make it easier for the view to present, or it may calculate the number of characters remaining for input for fields with a maximum length. The view model may also implement data validation logic to ensure data consistency.
The view model may also define logical states the view can use to provide visual changes in the UI. The view may define layout or styling changes that reflect the state of the view model. For example, the view model may define a state that indicates that data is being submitted asynchronously to a web service. The view can display an animation during this state to provide visual feedback to the user.
Typically, the view model will define commands or actions that can be represented in the UI and that the user can invoke. A common example is when the view model provides a Submit command that allows the user submit data to a web service or to a data repository. The view may choose to represent that command with a button so that the user can click the button to submit the data. Typically, when the command becomes unavailable, its associated UI representation becomes disabled. Commands provide a way to encapsulate user actions and to cleanly separate them from their visual representation in the UI.
To summarize, the view model has the following key characteristics:
The view model is a non-visual class and does not derive from any WPF base class. It encapsulates the presentation logic required to support a use case or user task in the application. The view model is testable independently of the view and the model.
The view model typically does not directly reference the view. It implements properties and commands to which the view can data bind. It notifies the view of any state changes via change notification events via the INotifyPropertyChanged and INotifyCollectionChanged interfaces.
The view model coordinates the view's interaction with the model. It may convert or manipulate data so that it can be easily consumed by the view and may implement additional properties that may not be present on the model. It may also implement data validation via the IDataErrorInfo or INotifyDataErrorInfo interfaces.
The view model may define logical states that the view can represent visually to the user.
This is a pretty broad topic based a lot on opinion. The MVVM model isn't a set-in-stone thing, and there's lots of different ways of implementing it.
The ViewModel, in my opinion, has two main purposes:
1) To expose the Model to the View. There's two ways of doing this. Having your Model wrap your CRUD object and manage NotifyPropertyChange. In this case, it's common for your ViewModel to just expose the Model to the View and not do much else with it, the View binding directly to the Model, or via simple pass-through properties.
The other common scenario is just to have your model as a CRUD. In this case, the ViewModel manages the NotifyPropertyChange notifications and manages model updates, etc.
2) To manage Presentation logic and data. There's lots of things that you need to bind to and store that have no place in the Model. The Model is the data. It's most likely loaded from a database. Yet the View needs to track other properties. An example: say your city object is displayed in a list, and you want to show or hide it with a button. The logic for hiding it, and the boolean for it being hidden doesn't belong in the View, and has nothing to do with the base data in the Model, so it sits in the ViewModel.
Similarly, maybe you have a CityPopulation property. In your view you want to highlight cities that are larger than 1,000,000 population in red. Your View Model has the a property:
bool LargeCity
{
return CityPopulation<1000000;
}
And you render the label with a style trigger.
Another example, a ViewModel containing a Brush property to bind to, which I think is probably a common but bad practice. slugster also comments below that visual elements should not be present in the ViewModel.
Brush HighlightBrush
{
get
{
if (CityPopulation<1000000)
{
return Brushes.Red;
}
else
{
return Brushes.Black;
}
}
1- In many examples I've seen, they recreate the same fields again in
VM. What is the purpose, is it enough to have the whole object (City
in my example). How about if there are many fields!.
Since the view model is the responsible of implementing view's logic and it performs actions against the model, there're some cases where some properties wouldn't be necessarily part of the model, but they're just there to serve view's requirements.
For example, let's say your model has a Name and Surname, and you want to show a concatenation of both properties in your view. You may be able to implement this using binding expressions or implementing a property in your view model:
public string FullName => $"{Model.Name} {Model.Surname}";
2- To be able, to use it in my View (CRUD), how is the CityVm() will
be in my example?.
This question has no specific answer. But you'll need a Model property at least to store a given City.
First off let me say this is my first attempt into trying MVP. I am going for the Passive View approach as I want to completely decouple the Views from the Model.
I have read up on MVP by reading the following articles among others
Derek Greer
http://aspiringcraftsman.com/2007/08/25/interactive-application-architecture/
Todd Snyder
http://blogs.infragistics.com/blogs/todd_snyder/archive/2007/10/17/mvc-or-mvp-pattern-whats-the-difference.aspx
My application is going to have 4 Views that are custom controls in which each implement a different interface to interact with the Presenter. Now this is not a problem for 3 of the views as the controls are static and never change.
My problem comes along where on the 4th View I need to change the control/View that is displayed based on events triggered from View 1.
So for example lets say View 1 is a list of people who can be from either an employee or a customer. Now depending on who is selected you can modify different parameters depending on the type of person selected. The problem is that View 4 needs to dynamically change the editing control based on what is selected. Keep in mind not only the properties will be different but how they are edited as well. Also each editing control is going to fire different events for property changes.
So how does my Presenter know how to manage interaction with the Model, when depending on whether an employee or customer is selected there is a different editor that implements a different View interface?
I hope that was clear. Any help is greatly appreciated. I have searched all over and all examples show a concrete relationship between the View and Presenter whereas mine needs to be extremely flexible.
My goal here is to keep the editing controls on the 4th View so flexible that I could for example add editing controls/Views for aliens or dogs or whatever else I might add to View1 to be selected.
Thanks
You can create a top-level presenter that listens for selection events and changes the editing control by instantiating different MVP triads based on what is selected. Typically in MVP your presenters manage all the construction/dependencies.
I personally don't like having a 'Master Presenter' per se. I do build composite presenters: e.g. View can contain one of several views, so I build a Presenter for the master view, which sends commands (messages, events, whatever) to a specific child presenter (I don't expose any View outside it's owning Presenter).
Don't over-complicate things ...use a different View for each responsibility. Views are cheap.
I have ListView control in windows forms that is due to display list of items in either icons view or in details view. I'd like to separate the ListView state logic and created 2 states classes IconsState and DetailsState inhereting them from IState having all the methods to be called from UI window.
In details view there is RetrieveVirtualItem event and in icons view there is DrawItem event. In order to call them from IState variable present in UI both States descendant classes have to implement them. Having DrawItem in DetailsState does nothing but return. The same for RetrieveVirtualItem in IconsState.
Is there another design approach to avoid implementation of empty methods in states?
Yes, there are better approaches. It's a design smell to force a class to have a member that is not supposed to be in there, ie in your words "Having DrawItem in DetailsState does nothing but return".
Alternatively, you can use an MVP pattern, which will allow you much greater testability. In a passive view variation of MVP you will have one model, two dumb views and a presenter that decides which view to render depending on the user choice.
Additional resources on MVP:
SO tag for MVP
Passive view sample
MVP examples for Windows Forms
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/