Showing another View from my current Viewmodel and closing a view from my viewmodel? - mvvm

I have another view setup and ready and waiting with its viewmodel. My RelayCommand arrives in my "Current" viewmodel. What is the best way to show the new view from my current viewmodel?
I have been reading and it appears that I need to use the Messenger to send a message from my viewmodel to ??? my new viewmodel that is associated with my view I wish to show? But how would I show the View?
Also is there a way to support closing a view from a viewmodel? I wonder if mvvm-light brings anything extra to the table - ie.. Triggers to force the viewmodel to close the view?

In WPF, you have two ways (out of the box) for "showing"/"closing" views. The first, is simply, by showing a Window, or Dialog via the .Show() or .ShowDialog() methods, and they can be closed with the .Close() method. In this case, you can use the MVVMLight Messenger class as you mentioned to send the show/close messages to the view in a decoupled way. here's an example with "closing".
In the ViewModel:
CloseTheView()
{
Messenger.Default.Send(new CloseTheViewMessage);
}
in the code-behind of your view:
//Constructor
public TheView()
{
...
Messenger.Default.Register<CloseTheViewMessage>( () => this.Close() );
}
as you can see, this involves some code in the code-behind file, but it's no big deal, since it's just one line of functionality.
The second approach is to use the Navigation Framework (which is available for both WPF and Silverlight). You define a "Shell" which is the main Window (or UserControl), you put a frame inside of it, and you make your other views inherit from Page, and then initiate the navigation from your ViewModel using the instance of the NavigationService associated with Frame (or directly the one associated with the page itself).
Hope this helps :)

Related

How to Dispose a ViewModel after Popping a page with Xamarin.Forms?

What I would like to do is unsubscribe from events at the moment the ViewModel is no longer needed. I tried implementing IDisposable but nobody calls Dispose(), not Xamarin.Forms nor Prism.Forms.
We have an app created with Xamarin.Forms. We use Prism.Forms to do MVVM. When navigating to a new page (push on stack) Prism.Forms wires the ViewModel to the Page. When navigating back (pop from stack) the ViewModel gets GarbageCollected after a while.
The problem is however that at a point in time we have a couple of the same type of ViewModels with subscriptions to events that are not bound to a View. When the events fire all these ViewModels start doing their thing. So I am looking for a way to unsubscribe at the moment the subscription is no longer needed.
Does anyone have a solution?
You can make sure the Dispose() is called in the OnDisappearing() event of the View, if you want to ensure that ViewModel is not present anymore in the memory than the view.
It is better if you care only about subscribe and unsubscribe of events, then to do it in the OnAppearing() and OnDisappearing(). In that case you will be sure of no event handlers been present on the viewmodel once view is not visible.
Implement IDestructible or INavigationAware
(or both as in BaseViewModelsample from Prism).
Depending on your object lifecycle :
Implement your disposal code in the Destroy method of IDestructible interface.
Implement your disappearing/appearing code in the OnNavigatedFrom/OnNavigatedTo methods on INavigationAware interface.
Bonus:
IDestructible can be implemented also by the View (and it will called accordingly by Prism when the view is destroyed).
Note:
While the solution above using OnAppearing/OnDisappearing works, it induces that ViewModel will depends on a call from View for managing its lifecycle (not clean). Moreover these methods don't exist on ContentView.

Who should create view model instances in MvvmCross

Just to make it clear: I know MvvmCross is very flexible about where and how view models can be created. My question is more about proper separation of concerns, to simplify design of complex cross-platform applications.
Consider we have an app with customer list and customer details. On iPad and Surface the list and details are shown on the same page, but on smaller devices customer list and details for a selected customer are split between separate pages. So we have a PCL with CustomerListViewModel and CustomerDetailsViewModel. Now how should we manage view model lifetime from within the portable class library?
I originally did it using code in CustomerListViewModel implementation that looks like this:
public ICommand SelectCustomerCommand
{
get { return new MvxCommand(SelectCustomer); }
}
public void SelectCustomer()
{
if (formFactor == FormFactor.Phone)
{
ShowViewModel<CustomerDetailsViewModel>(new CustomerDetailsViewModel.NavObject(this.SelectedCustomer));
}
else
{
this.CustomerDetails = new CustomerDetailsViewModel(this.SelectedCustomer);
}
}
What is essential here is that we either call ShowViewModel that in turns asks a presenter to construct a CustomerDetailsViewModel object and render it in a new page or explicitly create an instance of CustomerDetailsViewModel and bind it to CustomerDetails.
After having seen episodes 32 and 42 of N+1 MvvmCross video series I am not quire sure this is the right way to do it. Of course it works, but should a view model care about instantiation details of other view model?
My second thought was to refactor this code and put this logic into a presenter, so I can simply write in CustomerListViewModel implementation:
public void SelectCustomer()
{
ShowViewModel<CustomerDetailsViewModel>(new CustomerDetailsViewModel.NavObject(this.SelectedCustomer));
}
... and presenter will do the rest inside the code triggered by ShowViewModel call. However, in the episode 42 it's shown how to control view model lifetime right from the associated view:
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
VisibleViewModel.IsVisible(false);
if (e.NavigationMode == NavigationMode.Back)
KillableViewModel.KillMe();
}
But if a view model lifetime is controlled by a presenter, shouldn't we try to place KillMe call inside presenter's logic? I know so small piece of code doesn't make much difference but couldn't this be an advantage to put it in presenter's class and reduce code-behind?
Definitely the ViewModel should not handle anything in regards to view (screen).
One quick idea I have is use a custom presenter which is able to create views based on the ShowViewModel<> requests.
The custom presenter is a view responsibility so you can test for screen orientation.
http://slodge.blogspot.co.uk/2013/06/presenter-roundup.html
For the second part of this question:
But if a view model lifetime is controlled by a presenter, shouldn't we try to place KillMe call inside presenter's logic? I know so small piece of code doesn't make much difference but couldn't this be an advantage to put it in presenter's class and reduce code-behind?
Currently view model presentation is orchestrated by the presenter - it gets ViewModelRequest objects and decides what to do with them.
However, it doesn't normally create the ViewModels - instead:
the presenter normally creates/shows a View
then the View creates (or locates) a ViewModel as part of the OnCreate, ViewDidLoad or OnNavigatedTo handling.
And so I don't think a ViewModel's lifetime is normally "controlled by a presenter" - instead I think a ViewModel is a "Model for a View" - so it's lifetime is "controlled by its view".
For the occasions where you need shutdown/dispose/killMe logic in your ViewModel, if you wanted to move that logic back inside the presenter - or into some other object - then you definitely could do so if you wanted to - it's your app and the app is king.
However, in these cases I suspect you would need the presenter to get some kind of notification from the View - as often the presenter doesn't know when Views are removed (when a modal is dismissed, when a Back button is pressed, when Android clears up stack views to save memory, etc).
As another way of thinking about this, if the presenter were renamed as INavigationService then what roles do you want that INavigationService to own within your app?

Implementing MVVMC and Dependency Injection

I have just read this article about MVVMC pattern. Now I have a question. Should Controller be injected to ViewModel, or ViewModel should be injected into Controller?
The MVVMC is simply a MVC where the View is replaced by a ViewModel pair.
The View interacts ONLY with the ViewModel taking advantage of the powerful data binding mechanisms in XAML based technologies.
The ViewModel can notify the Controller but SHOULD NEVER inject a controller.
I have put together a simply sample based on the well know sample of Josh Smith on MSDN... where I have introduced a Controller.
It depends on what you are doing. I'm going to guess that most of the time the Controller would not need to be injected into either, but if it is needed, it is more likely to be needed in the ViewModel. Let me explain.
What are you doing with the controller? You must be doing something.. If that "something" is solely related to "what the data looks like", then it belongs in the View. If it is related to "what is be being shown to the user" then it belongs in the ViewModel.
I'm injecting a controller into one of my ViewModels. My ViewModel represents data which is then graphed in the View. I have a command which moves a data item from the current graph to a new graph. Since this changes "what is being displayed in the graph window" I implemented the command in my ViewModel. The ViewModel removes the data item from its own collection of items, and then uses the Controller to request a new view be created for that new data (it already had this functionality).
Looking at the article, I don't see arrows between the controller and the view
The ViewModel is a contract between the View and the Controller, and ideally does not need to know about (be dependent on) either.
So I definitely wouldn't be injecting a Controller into a ViewModel.
I'm not sure I'd be doing the opposite either: the controller is normally responsible for creating new ViewModel instances. If you want to go for a more loosely coupled implementation, you could go for injecting an abstract factory into the Controller, to avoid directly creating new instances of your ViewModel classes.
I believe the Controller should be injected as an abstraction IController. The ViewModel needs IController to be able to navigate to a different View/ViewModel.
For example, in ViewModel:
IController _controller;
public MyViewModel(IController controller){
_controller = controller;
}
void NavigateHome();
{
_controller.NavigateHome();
}
The abstraction IController is better than injecting the Controller itself for these reasons:
Testability. You can inject a mock IController and test the ViewModel
Decoupling. ViewModel doesn't have to know Controller.
I developed a lightweight framework for doing MVVMC in WPF.
It has a lot of resemblance to MVC in Asp.NET Core.
Check it out if you're looking for a WPF solution.
Blog post with documentation:
http://michaelscodingspot.com/2017/02/15/wpf-page-navigation-like-mvc-part-2-mvvmc-framework/
GitHub:
https://github.com/michaelscodingspot/WPF_MVVMC

GWT MVP UiBinder - passing arguments to the presenter

I've started a GWT project, I've decided to give the UiBinder a try. I'm having a difficult time laying an MVP pattern on top of UiBinder.
When I was using GWT-pure-java: I'd use Gin to inject my presenter with the corresponding view. It was pretty straight forward, and if I wanted to pass an id into the presenter, then I would simply pass an id into the presenter's constructor.
Not so straight forward with UiBinder. I'm almost certain that I'm missing something, because lots of people are claiming that UiBinder and MVP are a match made in heaven...so I'm hoping to get some solid responses on this query ;-)
What I've seen in several trivial GWT-UiBinder examples, is that the view is created by the binder then either:
The view constructs the presenter either in its constructor or via a #UIFactory method.
The corresponding presenter is passed to the view (via a setter, needless to say after the view is constructed).
With the first approach, how does one pass an id to the presenter if the presenter is being constructed in the view? Would you do view.getPresenter().setId(42);, and then the presenter would go to the server get some info and ask the view to display it...smells bad.
With the second approach, one would end up with a non-intuitive object graph in which it is not clear who is the consumer and who is the producer. Also, in situations where the view requires information from the presenter (almost all use-cases require this) what would one do:
//some code would create the presenter pass it the id and then call view.setPresenter
class MyView {
void setPresenter(MyPresenter p) {
this.presenter = p;
//OK now that i have my presenter how do I ask it to fetch data from the server.
//do i turn around and do: presenter.setView(this); and then the presenter takes
//over and uses the view to display the data?
}
}
This is equally smelly...Sorry for the long post, and thanks in advance...
You're right in that it does seem a bit unclean to have both a View reference its Presenter, and have the presenter reference the View.
The way I see it, and how the google dev pages on MVP outline there are two flavours of MVP:
Have a view that doesn't know about its presenter, and "wrap" it with a presenter. The view provides a sufficient API for the presenter to get/set all the data it cares about. Additionally the presenter must know about all event types the view can generate, in order to respond to user interaction. This is the method of MPV part 1.
The presenter once more knows about the view, but this time only in a get/set data capacity. The presenter does not concern itself with the UI events in the view. Instead, the presenter provides an API for the view to call/notify it when events happen in the form of "onSomethingHappened()" methods in our presenter. This allows us to capture all behaviour/logic in the presenter itself, and invoke it as necessary when something happens in the view. The view can then handle events at a very low level in any way suitable - whether using GWT events/widgets or raw DOM events with elements/HTML (UiBinder/GWT performance best practices). This is the method of MVP part 2.
I prefer option 2 as it allows the presenter to be purely focused on the necessary behaviour. The view can deal with widgets/html/event handling as necessary and simplify it to calls to "onSomething()" calls for the presenter. Those widget/event implementations might be simple or complex and optimized events. The presenter is unaffected (and unpolluted) by the detail, as it just gets notified. I feel this option is a cleaner separation of presentation and behaviour. Note it's also a 1 to 1 implementation of the Observer Pattern, so the interconnection between View and Presenter is necessary.
As for creation, I feel the Presenter is the stronger entity despite it playing the Observer role. I would create the necessary presenter and then pass it the view of concern. The presenter can then take control of the view, and pass the view a self reference.
As for your producer/consumer analogy I think the presenter is the consumer. The view produces UI events (user interaction) and the presenter responds by providing the necessary behaviour. That should be the only point of contact between the view and presenter - the view calls methods like "onSomethingHappened()" and the presenter does the work. The view would never tell the presenter "fetchData()" or anything like that.
I've just started using UiBinder + MVP recently myself, so this is just what I think. I hope it helps!
It has been a few days since I started this thread and read the responses. I've decided on my approach. And I'd thought I just mention it here.
Once again, thanks for the thoughtful responses...they were helpful.
As filip-fku pointed out presenters are the main entity, so I decided to continue to threat them as such during the life-cycle management of my mvp objects. In other words, the views do not instantiate the presenters. The presenters are instantiated by other presenters (at some point i'll delegate to Gin).
The builder of a presenter has access to its corresponding view, and injects the presenter (via constructor) with the view.
The views themselves are either instantiated by the builder or instantiated by UiBinder as part of a larger view. In the latter case where UiBinder instantiates the view the parent view has a getter. Here is an example of this case:
/*pojo for the parent ui-binder*/
public class Form implements FormPresenter.View {
#UiField PromptView namePrompt;
#override
PromptPresenter.View getNamePromptDisplay() {
return namePrompt; //introduced into this pojo via #UiField
}
//bunch of view code
}//end of the class
Then in the FormPresenter I do:
private void buildNamePrompt() {
new PromptPresenter(display.getNamePromptDisplay(), etc....);
}
I have essentially kept the mvp life-cycle similar to the pure java approach. Once I get some milage out of this, I'll refactor it with Gin.
Thanks again.
P.S. if you haven't seen the i/o presentation mentioned above, it is worth checking out.

MVVM - Should the View have a reference to the Presenter/ViewModel?

I've been looking through the PRISM 2 samples for ideas about how to best approach a new application I'm working on, which will be a PRISM 2/WPF app. Looking in particular at the View Injection sample application that ships with PRISM I've noticed that all of the views implement an interface which allows the presenter (or ViewModel) to interact with the View.
In the past I've done this the opposite way round, I inject the presenter into the view so that the view can directly call to methods on the presenter a bit like this:
public partial class SomeView : ModuleBase
{
private ISomePresenter _somePresenter;
public SomeView (ISomePresenter somePresenter):this()
{
// Give the view a reference to the presenter
_somePresenter = somePresenter;
// Bind the View to the presenter
DataContext = _somePresenter;
}
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
// The view can call actions directly on the presenter (OK I should probably use a command for this)
_somePresenter.SomeAction();
}
}
The technique above seemed reasonable enough to me, but looking at the samples I'm starting to question the approach. Does anyone have views (no pun intended) on the best way to go about this?
Add the presenter to the view and get the view to interact with the presenter
Add the view to the presenter and get the presenter to interact with the view
Something totally different that I haven't thought of yet?
The most common approach to map a ViewModel to a View in MVVM is to use a DataTemplate :
<DataTemplate DataType="{x:Type vm:SomeViewModel}">
<v:SomeView />
</DataTemplate>
When you display a ViewModel instance in a ContentControl or ItemsControl, WPF will automatically instantiate the appropriate View for the ViewModel, and set the View's DataContext to the ViewModel instance.
That way, you don't have any reference to the View in the ViewModel, and the View only references the ViewModel through the DataContext property. In case you really need to access the ViewModel in the View's code-behind, you can always cast the DataContext (but this implies that the View knows about the ViewModel's actual type, which induces coupling)
I think it's all a matter of taste. Personally, I enjoy the way you see it in samples you are looking at. IView has one method, thats SetViewModel(...). IViewModel has a property called View of type Object, that essentially returns the DI instantiated IView.
The reason I like this way is I almost always want to create a ViewModel first and I want nobody in the code to be able to do anything with my IView, except get reference to the instance (for view injection or binding the view to say a ContentControl), which is why its of type object. If any code needs to talk to the View, for me, it's always via the VM...and even then the view gets updated usually via binding. It would feel odd to go from the View->ViewModel->UpdateBinding->View, than it is, VM->UpdateBinding->View
To answer the question, I generally don't need a reference to the presenter in the codebehind. Usually I can handle that with commands from the view being bound to the VM.
In some cases, you might want to keep reference to the presenter to do what you have in your example, but it is avoidable given the correct toolset (makes SL harder that it doesn't have built in commands).
Like I said, it's all a matter of taste...
-Jer