Reusing ViewModel with single View-Instance - mef

I use an MEF exported ViewModel (ReportViewModel) multiple times in my application.
<ContentControl cal:View.Model="{Binding ReportVM}" />
As expected, the same instance of the ViewModel is always used.
But it seems that caliburn always create a new View instance.
How can I prevent caliburn from creating a new View instance?
Is this possible?

Related

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

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

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 :)

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

Controllers in MVVM, How to get info from viewmodel to it's controller?

We are building an app using the MVVM pattern, we have controllers that wire up all the views and viewmodels using DI. All examples of MVVM I've seen are really simplistic and have 1 view. How do/should viewmodels talk back to the controller? The controller knows about the models and views, should the viewmodel send events back to the controller? Where should a save happen? Model? Controller?
Could your ViewModel not take a dependency on an IController or some other interface, so they can talk back to it? I try to keep as much application logic out of the ViewModel as possible, as these classes can easily become bloated.
MyViewModel(IController controller)
{
this.controller = controller;
}
void Save()
{
this.controller.Save();
}
I do agree that the MVVM frameworks tend to be too simplistic with their samples. In particular, moving between views/screens in your application is something I would like to see more examples of. I create an IViewManager interface, to allow my ViewModels to request that we move to another view.
We use Controllers too but in our case they are responsible for the application workflow. The Controller knows the ViewModel and the Model but not the concrete View because this will be injected by the IoC Container.
If you are interested in an example that shows more than just one UI (modal dialog, wizard with conditional workflow) then you might have a look at:
WPF Application Framework (WAF) - http://waf.codeplex.com
In case of an application that has multiple modules and requires separation of concerns I would recommend using prism framework.
http://msdn.microsoft.com/en-us/library/gg406140.aspx
I use a similar setup to you. In my controller, where my DI and view injection goes down, I sometimes keep reference to the ViewModel (which hold the View). Some cases I may have an event on the VM which is handled by the controller. In other, extreme cases (like if the VM/V was created outside the controller, say in another VM), I may even use the EventAggregator (with a strong ref) to listen to events that may be fired on the VM. In that case, a stored ref to the VM is not needed.
How about using events wherein the controller subscribes to VM events or using a mediator pattern where in a mediator is injected in a VM.

In MVC where do you put references to your model Classes?

I have been wondering for a while, after asking different people and without any of them providing what I would call an "at least a bit concrete answer":
Question:
Where, in an iPhone application should an application keep the references to it's Model Classes (using the MVC approach) ?
In iPhone (and Cocoa) applications we have what we call the "App Delegate", which basically start's up our application and inits our controllers, also handles UITouch events.
So is the App Delegate a controller ? a model class ? none of the two ? I think not knowing that also makes confusing to know where to put the Model References.
Example:
You have the Application Delegate, that delegate contains a reference to your Application's View Controller. If my Application would use Model Class A ( which is a webserver daemon class ), and a Class B which stores data queried by that webserver.
Where would you guys store the references to A and B ? (App Delegate ? View Controller ? Both ? )
There are many options here, but as an example, I would really like to know how would you guys use mvc to put together this application which only uses one View.
It is tempting to put everything in the AppDelegate, but if you start doing this, then your AppDelegate will be full of reference hacks. If you are doing a strict MVC, then you should have 3 things:
A Model
A View Controller (Only for view logic)
A Controller (For coordinating between the view and the model)
So for example, I have a model Foo and a Foo controller. I would have:
Foo.m (Model)
FooViewController.m (Displays a Foo)
FooController.m (Controls the logic)
And finally, to answer your question, I would store my references to Foo's in the foo Controller. I like to use singletons for my controllers, but thats just me. If you do use a singleton, you can just do something like this: [[FooController sharedInstance] listOfFoos] to get your Foo's
In my applications I usually rename the AppDelegate class to AppController, if that helps explain things better conceptually. Your app controller is responsible for creating and/or configuring the model controller (which manages your collection of model objects) and window or view controllers, setting up references between them if needed, and calling methods on these controllers in response to NSApplication delegate methods or high level action methods from the main menu. Depending on how complex your application is you might also have additional model or view controllers which are created outside your app controller.
Of course if you have a simple application there's no real reason not to have your app controller play the role of the model controller if you want. What you want to avoid is file with hundreds of lines of code, all doing conceptually unrelated tasks.
Traditionally the controller creates the Model and then initialises the View with that model. The controller then listens to changes in the model and view and coordinates the flow of the program through this. That would be my generic answer, maybe things in practice would be different for iPhone development.
Where, in an iPhone application should an application keep the references to it's Model Classes ( using the MVC approach) ?
The controller layer keeps references to the model layer.
So is the App Delegate a controller ? a model class ? none of the two ?
The App Delegate is a controller.
Where would you guys store the references to A and B ?
A and B are model classes that would usually be created and owned by the controller layer.
I would really like to know how would you guys use mvc to put together this application which only uses one View.
The purpose of the controller layer is to allow the model and view layers to be self-contained. The model shouldn't know anything about the controller or view layers. The view shouldn't know anything about the controller or model layers. The controller's job is to be a double-ended adapter to the model on one side and the view on the other.
I would set up your example app like this:
UIApplication delegates to AppDelegate.
If operation of your server class (A) is simple:
AppDelegate creates and owns instance(s) of server class A.
If operation of your server class (A) is complicated:
Create a dedicated controller class (C) to control the server.
AppDelegate creates and owns instance(s) of class C. One instance of (C) for each instance of (A).
Each instance of class C creates and owns one instance of class A.
AppDelegate creates and owns an instance of your ViewController class, which loads and owns your view.
It's not clear in the question what the purpose of class B is.
If it's a chunk of data that's for the use of A only (like config data or static website data), I would have it be created and owned by the server (A).
If it's data that is created during server operation and needs to be displayed in the view, then you will probably want something like:
A mutable array owned by A, to hold instances of B.
Another controller class (D) to reference that array and act as a datasource/delegate to your view.
I find that in most instances, AppDelegate provides a good place to place some base functionality (such as a a background image you want applied in every controller), but that you'll want to have additional controllers and model code elsewhere. A navController or rootController would often be placed as a property on your AppDelegate.
So, I would say that is somewhere between "neither" and "controller", but leaning more towards "neither". Definitely not "model"!