MVPVM - Event handling using Interface or Presenter - c#

Handling button click, row double click and other events. What is a better approach?
Direct Access of presenter to View. So the view can directly call the appropriate method on the presenter, eg. Presenter.Save()
Or
Event in interface.
interface ILoginDetailView:
{
event EventHandler Save;
}
View
private void btnSave_Click(object sender, EventArgs e)
{
Save(this, null)
}
Presenter
view.Save += new EventHandler(view_Save);
I feel the 2nd approach is better as it makes the view decoupled from the presenter. But in all the articles/papers where the pattern is described, 1st approach is used.

Personally, I always go for the second approach. Generally, I don't like having the view know about the presenter, and the decoupling is a great advantage. Otherwise, I find myself making functions taking specific variables from the view. The event pattern breaks that nicely.

I also would go with the second approach, because as you stated that decouples the view from the presenter, which in turn makes that stuff testable.

In the MVPVM (model view presenter view model) pattern it's stated that the view is usually tightly coupled to your view. This allows your view-model, view, and business/data access layers to remain decoupled.
So once again, the presenter can be tightly to allow direct access to the view without adding responsibility to your view model or view.
MVPVM Design Pattern
It's a great article and discusses MVC, MVP, MVVM, and MVPVM verly well.

I think the first approach is much cleaner.
A Save just doesn't feel like an event. It's a direct action.
In MVVM you're calling a command on the viewmodel, in MVC you're calling an action on a controller and in MVP you're calling a method on the presenter.
A Saved or Saving is an event, but not Save.
But it's probably a question about personal preferences.

Related

WPF MVVM calling ViewModel methods from code behind

First off I am very new to WPF MVVM and a bit confused. People say that generally in MVVM the best practice is not to have any code behind. I have found that some methods are way easier to achieve in code behind than in viewmodel (e.g MouseMove) and that led me thinking between the differences of these 2 following examples:
1) Using RelayCommand:
View
<Button Command="{Binding AlertCommand}"></Button>
ViewModel
public RelayCommand AlertCommand { get; set; }
public void Alert()
{
MessageBox.Show("message");
}
2) calling ViewModel methods from code behind:
View
<Button PreviewMouseLeftButtonUp="OnMouseLeftButtonUp"></Button>
View code behind
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var ctx = (MainViewModel) this.DataContext;
ctx.Alert();
}
Is using code behind here wrong? What are my benefits of not using code behind?
The MVVM pattern is a best practice when building UWP, WPF, and Xamarin.Forms apps. The main advantage is that you are able to decouple the logic from the presentation and potentially could present a single view model by multiple different views and could switch views without having to modify the view model significantly. This is a great advantage when building cross-platform apps with native UI, which MvvmCross framework uses to a great extent for example.
Having an empty code-behind is however definitely just an ideal, which is usually not easy and not always necessary to achieve. Sometimes you need to use code-behind for purely view-related manipulation like changing layout for different window sizes, controlling animations, etc. For such actions, code-behind is a much better fit than trying to force this somehow into the VM.
Comparing your two approaches, using the RelayCommand-based one over the direct method call is preferable, because it has less direct tie to the method itself. If you wanted, you could switch the RelayCommand instance in the VM for a different implementation (calling different method) at runtime, and thanks to binding the button could now perform a different action. This can be used in editor-like apps where some tools may have different functionality based on current context the app is in.
Also, for controls which do not offer a Command you can use EventTrigger hand in hand with InvokeCommandAction (both defined withing Expression Blend SDK) which will allow you to "convert" an event to a command call, even with your defined transformation of EventArgs.
Both are valid methods. The first is preferable if possible. I generally use the second method on events where no command binding is available. The notion of "absolutely no code-behind in MVVM" is debatable. Any code that belongs directly to the view (and is not business logic) and is not reusable in a VM can be put in the code-behind, such as wiring up events in the second example.

Clean and elegant view models in WPF

Once I found out MVVM I really liked it. The whole concept of binding, separating view from logic, testability, etc was very encouraging. It was a nice alternative for the messy, never-ending code behind. Than I learned there are commands that can be bound, which I also liked at first.
Having written a couple of controls using MVVM though I found out that my view models start to look more or less like code behind. Full of commands that did almost exactly what was previously done in code behind by event handlers.
Let me give you some examples.
There is a control with a button "Details" which opens another window.
[approach 1]
The first (and worst) thing you can do is call something like this in your command:
new DetailsWindow().ShowDialog();
That makes the view model strongly reference the presentation layer - ugly.
[approach 2]
Lets fix this problem using a weak reference and create something like IDialogService. We can inject a simple implementation that creates and opens the window. Now we got rid of the strong reference to the presentation layer and the command can look like this:
_dialogService.ShowDetailsWindow();
I still don't like this approach. To me it feels like the view model is not something that should decide whether to show a window or not. It should serve and handle data.
[approach 3]
The elegant way to totally separate the view model from the presentation layer would be to inject the command itself. Than the view model would not be aware of presentation layer. It would only execute the injected action - no matter what it is.
Question 1:
Which approach would be best? I guess the number 3 is the winner.
Question 2:
Should this even be a part of the view model? I think it shouldn't as it seems to be the concern of the presentation layer. Maybe it's best to put it in a simple event handler in code behind?
The second example is more complex. In the same control we have a "Delete" button. It should open a dialog asking user for confirmation and if he says 'yes' it should delete something. In this case it makes more sense to put it in the view model as it really affects the data.
Question 3
This case is the most tricky for me. I can't use my favorite approach number 3, because I have to display a dialog which is a presentation layer's job, but also I have to perform some logic depending the dialog's result - which on the other hand is view model's job. What is the best approach here?
Please bare in mind that I really don't want to use approaches 1 and 2. I want the view model to be clean and unaware of anything related to the presentation layer - not even by weak references.
One thing that comes to my mind it to split the view model layer into two layers. Something like:
view --> presentation view model --> logic view model
presentation view model
used as a control's context
contains logic view model as a public property for direct bindings
uses approach number 2 - now it's acceptable as the whole class is meant to perform presentation related actions
logic view model
it is 'presentation free'
references specialized logic services
some commands could be bound directly to the view
some commands could be executed by the presentation view model which owns it
Maybe this is the right way to go?
[EDIT]
In response to the suggestions in comments about using a framework:
Using a framework will surely make it easier to handle windows, but it's not the solution to the problem. I don't want the 'logic view model' to handle windows at all, not even with a help of a framework. Referring to the approach I suggested at the end I would still put it in the 'presentation view model'
Your ViewModel should just notify all the subscribers that the command was executed by firing a simple event. The View should subscribe to that event and handle the event by displaying a new Window...
ViewModel:
public event EventHandler<NotificationEventArgs<string>> DisplayDetailsNotice;
private DelegateCommand displayDetailsCommand;
public DelegateCommand DisplayDetailsCommand
{
get { return displayDetailsCommand ?? (displayDetailsCommand = new DelegateCommand(DisplayDetails)); }
}
public void DisplayDetailsWindow()
{
//
Notify(DisplayDetailsNotice, new NotificationEventArgs<string("DisplayDetails"));
}
View (note that the VM is already the DataContext of the View):
private readonly MyViewModel mvm;
//Get reference to VM and subscribe to VM event(s) in Constructor
mvm = DataContext as MyViewModel;
if (mvm == null) return;
mvm.DisplayDetailsNotice += DisplayDetails;
private void DisplayDetails(object sender, NotificationEventArgs<string> e)
{
DetailsWindow = new DetailsWindow { Owner = this };
DetailsWindow.ShowDialog();
}
This way, when the command is executed the VM raises the event and the View which is subscribed to VM events handles the event by displaying the details windows using the ShowDialog() method. Since all the VM does is publish an event it remains agnostic of and decoupled from the View leaving the MVVM pattern intact. Since VM is already the DataContext of the View and the View binds to properties of the VM as it is obtaining a reference to the VM is also not breaking the MVVM pattern...
Note that this syntax is valid with Simple MVVM Toolkit MVVM framework. As suggested in comments you should start using an MVVM framework (my recommendations are Simple MVVM Toolkit or MVVM Light, Caliburn is too complex for no reason and no gain IMO) in order to avoid having to deal with the plumbing yourself...

ASP.NET MVP Pattern

I'm trying to implement the Model-View-Presenter design pattern in my application.
The general concept of the MVP pattern is known for me, but I'm more struggling with getting it done using nested usercontrols.
I've got a few possible scenarios I might be able to implement, but before doing so I'd like to hear your opinion.
I think it does not matter to post any of my code, since its more a "concept" I'm trying to understand.
So the scenario is:
1 page used to connect 2 user controls. One of these usercontrols contains a child usercontrol. How do I work around with MVP pattern in this case?
1 Page
1 UC
1 UC
1 SubUC
Edit:
So basicly what I want to know is how we can interact between two views (parent and child) using MVP in both usercontrols.
I'll show you an example in ASP.net WITHOUT MVP:
http://pastie.org/5452134
Now with MVP, do we still register to this kind of event using the CodeBehind? Knowing that this parent and child usercontrol would both be using the MVP pattern. Or does the presenter get's included in this interaction?
Eventually I can change the code to:
http://pastie.org/5452180
But I'm wondering whether this is OK, considering the MVP pattern...
Or do we more need an approach like this:
http://pastie.org/5452174
All the above examples are written in the CodeBehind of the parent view. Is one of this correct? If not, how can we achieve this using a better approach
Edit 2: I've added a solution with my example approach at: https://github.com/frederikprijck/ASP.NET-MVP
I think this should be pretty much what I wanted...
I don't see a problem - user control is nothing but a view. And a presenter can interact with multiple views at a time. So in this case, your presenter can have reference of say 4 views (one for page, two for user controls and last one for sub-user control).
Alternatively, you want to have single view per presenter and in such case, you can see user control as child view of the parent view(page) and so parent view need to bubble up and down view interactions meant for presenter. However, I would prefer the earlier approach where presenter handling interaction multiple views.
See this related question on SO on how wiring is done: https://softwareengineering.stackexchange.com/questions/60774/model-view-presenter-implementation-thoughts
Finally, you may want to look at MVVM pattern which I believe works great for compositional UI. Instead of presenter, you will have view model that will control the interaction between view and model - however, unlike presenter, view model does not know about view - rather view observes (and updates) view model to render itself. See this article here (View Model is referred as Presentation Model): http://www.codeproject.com/Articles/23340/Presentation-Model-in-Action
EDIT:
To be honest, I don't prefer any of your approaches. I like MVP implementation where presenter holds reference to view via interface (no tight coupling) and view does the wiring i.e. creates presenter instance and inject the view references. The presenter listens to view events and call methods on view. View never calls directly on presenter's methods. (Other variations of MVP are possible - see the SO answer that I had sought). With this, I will explain two approaches that I had explained earlier.
Approach 1:
Each user control is an independent view. There will be common presenter that will handle multiple views. For example,
public class Presenter1
{
IView1 _view1;
IView2 _view2;
public Presenter1(IView1 view1, IView2 view2)
{
_view1 = view1;
_view2 = view2;
_view1.OnSave += OnSave;
_view1.OnSomeEvent += OnSomeEvent;
_view2.OnFoo += OnFoo;
}
public void OnSave()
{
var data1 = _view1.GetData();
var data2 = _view2.GetData();
// update model
...
}
public void OnSomeEvent()
{
// inform view2 about it
_view2.DoOnSomeEvent();
}
...
}
public partial class MyPage : Page, IView1
{
public void Page_Load(...)
{
//do wire up
_presenter = new Presenter(this, usercontrol1);
}
...
}
Basic idea is that view does not do cross talk. If user control needs to inform page some thing, it would raise an event that is caught by presenter and it informs page about it. Views are passive and handles UI.
Approach 2:
Usercontrol and Page interacts. In such case, Page will act as a ultimate view and Presenter will hold reference to it. Control's events will be handled by page and page will bubble up the event if necessary. For example,
IView1 : IView2 { }
public class Presenter1
{
IView1 _view1;
public Presenter1(IView1 view1)
{
_view1 = view1;
_view1.OnSave += OnSave;
_view1.OnSomeEvent += OnSomeEvent;
_view1.OnFoo += OnFoo;
}
...
}
public partial class MyPage : Page, IView1
{
public void Page_Load(...)
{
//do wire up
_presenter = new Presenter(this);
// handle user control events
UserControl1.Foo += UserControl1_OnFoo();
UserControl1.XyzEvent += UserControl1_XyzEvent();
}
...
private void UserControl1_OnFoo(...)
{
// bubble up to presenter
OnFoo(..)
}
private void UserControl1_XyzEvent(...)
{
// private interaction (purely about some UI manipulation),
// will not be bubble up to presenter
...
}
}

Winforms and the MVP Design Pattern? [duplicate]

I am trying to implement the MVP method for the first time, using WinForms.
I am trying to understand the function of each layer.
In my program I have a GUI button that when clicked upon opens a openfiledialog window.
So using MVP, the GUI handles the button click event and then calls presenter.openfile();
Within presenter.openfile(), should that then delegate the opening of that file to the model layer, or as there is no data or logic to process, should it simply act on the request and open the openfiledialog window?
Update: I have decided to offer a bounty as I feel I need further assistance on this, and preferably tailored to my specific points below, so that I have context.
Okay, after reading up on MVP, I have decided to implement the Passive View. Effectively I will have a bunch of controls on a Winform that will be handled by a Presenter and then the tasks delegated to the Model(s). My specific points are below:
When the winform loads, it has to obtain a treeview. Am I correct in thinking that the view should therefore call a method such as: presenter.gettree(), this in turn will delegate to the model, which will obtain the data for the treeview, create it and configure it, return it to the presenter, which in turn will pass to the view which will then simply assign it to, say, a panel?
Would this be the same for any data control on the Winform, as I also have a datagridview?
My App, has a number of model classes with the same assembly. It also supports a plugin architecture with plugins that need to be loaded at startup. Would the view simply call a presenter method, which in turn would call a method that loads the plugins and display the information in the view? Which tier would then control the plugin references. Would the view hold references to them or the presenter?
Am I correct in thinking that the view should handle every single thing about presentation, from treeview node colour, to datagrid size, etc?
I think that they are my main concerns and if I understand how the flow should be for these I think I will be okay.
This is my humble take on MVP and your specific issues.
First, anything that a user can interact with, or just be shown, is a view. The laws, behavior and characteristics of such a view is described by an interface. That interface can be implemented using a WinForms UI, a console UI, a web UI or even no UI at all (usually when testing a presenter) - the concrete implementation just doesn't matter as long as it obeys the laws of its view interface.
Second, a view is always controlled by a presenter. The laws, behavior and characteristics of such a presenter is also described by an interface. That interface has no interest in the concrete view implementation as long as it obeys the laws of its view interface.
Third, since a presenter controls its view, to minimize dependencies there's really no gain in having the view knowing anything at all about its presenter. There's an agreed contract between the presenter and the view and that's stated by the view interface.
The implications of Third are:
The presenter doesn't have any methods that the view can call, but the view has events that the presenter can subscribe to.
The presenter knows its view. I prefer to accomplish this with constructor injection on the concrete presenter.
The view has no idea what presenter is controlling it; it'll just never be provided any presenter.
For your issue, the above could look like this in somewhat simplified code:
interface IConfigurationView
{
event EventHandler SelectConfigurationFile;
void SetConfigurationFile(string fullPath);
void Show();
}
class ConfigurationView : IConfigurationView
{
Form form;
Button selectConfigurationFileButton;
Label fullPathLabel;
public event EventHandler SelectConfigurationFile;
public ConfigurationView()
{
// UI initialization.
this.selectConfigurationFileButton.Click += delegate
{
var Handler = this.SelectConfigurationFile;
if (Handler != null)
{
Handler(this, EventArgs.Empty);
}
};
}
public void SetConfigurationFile(string fullPath)
{
this.fullPathLabel.Text = fullPath;
}
public void Show()
{
this.form.ShowDialog();
}
}
interface IConfigurationPresenter
{
void ShowView();
}
class ConfigurationPresenter : IConfigurationPresenter
{
Configuration configuration = new Configuration();
IConfigurationView view;
public ConfigurationPresenter(IConfigurationView view)
{
this.view = view;
this.view.SelectConfigurationFile += delegate
{
// The ISelectFilePresenter and ISelectFileView behaviors
// are implicit here, but in a WinForms case, a call to
// OpenFileDialog wouldn't be too far fetched...
var selectFilePresenter = Gimme.The<ISelectFilePresenter>();
selectFilePresenter.ShowView();
this.configuration.FullPath = selectFilePresenter.FullPath;
this.view.SetConfigurationFile(this.configuration.FullPath);
};
}
public void ShowView()
{
this.view.SetConfigurationFile(this.configuration.FullPath);
this.view.Show();
}
}
In addition to the above, I usually have a base IView interface where I stash the Show() and any owner view or view title that my views usually benefit from.
To your questions:
1. When the winform loads, it has to obtain a treeview. Am I correct in thinking that the view should therefore call a method such as: presenter.gettree(), this in turn will delegate to the model, which will obtain the data for the treeview, create it and configure it, return it to the presenter, which in turn will pass to the view which will then simply assign it to, say, a panel?
I would call IConfigurationView.SetTreeData(...) from IConfigurationPresenter.ShowView(), right before the call to IConfigurationView.Show()
2. Would this be the same for any data control on the Winform, as I also have a datagridview?
Yes, I would call IConfigurationView.SetTableData(...) for that. It's up to the view to format the data given to it. The presenter simply obeys the view's contract that it wants tabular data.
3. My App, has a number of model classes with the same assembly. It also supports a plugin architecture with plugins that need to be loaded at startup. Would the view simply call a presenter method, which in turn would call a method that loads the plugins and display the information in the view? Which tier would then control the plugin references. Would the view hold references to them or the presenter?
If the plugins are view-related, then the views should know about them, but not the presenter. If they are all about data and model, then the view shouldn't have anything to do with them.
4. Am I correct in thinking that the view should handle every single thing about presentation, from treeview node colour, to datagrid size, etc?
Yes. Think about it as the presenter providing XML that describes data and the view that takes the data and applies a CSS stylesheet to it. In concrete terms, the presenter might call IRoadMapView.SetRoadCondition(RoadCondition.Slippery) and the view then renders the road in red color.
What about data for clicked nodes?
5. If when I click on the treenodes, should I pass through the specific node to the presenter and then from that the presenter would work out what data it needs and then asks the model for that data, before presenting it back to the view?
If possible, I would pass all data needed to present the tree in a view in one shot. But if some data is too large to be passed from the beginning or if it's dynamic in its nature and needs the "latest snapshot" from the model (via the presenter), then I would add something like event LoadNodeDetailsEventHandler LoadNodeDetails to the view interface, so that the presenter can subscribe to it, fetch the details of the node in LoadNodeDetailsEventArgs.Node (possibly via its ID of some kind) from the model, so that the view can update its shown node details when the event handler delegate returns. Note that async patterns of this might be needed if fetching the data might be too slow for a good user experience.
The presenter, which contains all logic in the view, should respond to the button being clicked as #JochemKempe says. In practical terms, the button click event handler calls presenter.OpenFile(). The presenter is then able to determine what should be done.
If it decides that the user must select a file, it calls back into the view (via a view interface) and let the view, which contains all UI technicalities, display the OpenFileDialog. This is a very important distinction in that the presenter should not be allowed to perform operations tied to the UI technology in use.
The selected file will then be returned to the presenter which continues its logic. This may involve whatever model or service should handle processing the file.
The primary reason for using an MVP pattern, imo is to separate the UI technology from the view logic. Thus the presenter orchestrates all logic while the view keeps it separated from UI logic. This has the very nice side effect of making the presenter fully unit testable.
Update: since the presenter is the embodiment of the logic found in one specific view, the view-presenter relationship is IMO a one-to-one relationship. And for all practical purposes, one view instance (say a Form) interacts with one presenter instance, and one presenter instance interacts with only one view instance.
That said, in my implementation of MVP with WinForms the presenter always interacts with the view through an interface representing the UI abilities of the view. There is no limitation on what view implements this interface, thus different "widgets" may implement the same view interface and reuse the presenter class.
The presenter should act on the request end show the openfiledialog window as you suggested. Since no data is required from the model the presenter can, and should, handle the request.
Let's assume you need the data to create some entities in your model. You can either pass the stream trough to the access layer where you have a method to create entities from the stream, but I suggest you handle the parsing of the file in your presenter and use a constructor or Create method per entity in your model.

MVVM Foundation: How to close Application Window from ViewModel

I am using MVVM Foundation but I think its quite straight-forward and not really framework specific. My setup is as follows:
StartViewModel - has a ExitCommand that returns a RelayCommand/ICommand
public ICommand ExitCommand {
get { return _exitCommand ?? (_exitCommand = new RelayCommand(() => MessageBox.Show("Hello World"))); }
}
public RelayCommand _exitCommand;
StartView (User Control) has a button binded to the ExitCommand
<Button Content="Exit" Command="{Binding ExitCommand}" />
First, read as much as you can stomach on MVVM, e.g. WPF Apps With The Model-View-ViewModel Design Pattern on MSDN. Once you understand the basic principles driving it the answer will seem more reasonable.
Basically you want to keep your View (UI) and ViewModel (essentially abstract UI, but also abstract Model) layers separate and decoupled. Showing a message box or closing a window should be considered a UI specific detail and therefore implemented in the View, or in the case of a message box, more generally available via a 'Service'.
With respect to the ViewModel, this is achieved using Inversion of Control (IoC). Take the message box example above. Rather than showing the message box itself, it takes a dependency on an IMessageBoxService which has a Show method and the ViewModel calls that instead - delegating responsibility. This could be taken further by leveraging Dependency Injection (DI) containers.
Another approach used for closing a View window might be for the ViewModel to expose an event, called for example RequestClose (as in the MSDN article), that the View subscribes to. Then the ViewModel would raise the event when it wants the corresponding View / window to close; it assumes something else is listening and will take responsibility and actually do it.
you can implement an CloseEvent in your StartViewModel. in your StartView you have to register this CloseEvent. when you Raise your closeevent from your VM then, your View recognize that it has to close your app/window.

Categories

Resources