I am looking for a solution/mvvm framework that supports nesting ViewModels and Views. What I mean is:
Each ViewModel derives from BaseViewModel
ViewModels have properties that are of type BaseViewModel which are sub-ViewModels (nested inside parent ViewModel)
Each ViewModel have corresponding View
Views have ContentControl (control that can display templated view) corresponding to sub-ViewModels of corresponding ViewModel
Now, when creating instance of ViewModel it is needed to pass appropriate instances of concrete sub-ViewModels. Views should be automatically resolved and nested (somehow) base on ViewModels structure.
I do not define somehow because there may be a lot of ways to do it.
I hope my idea is clear. This approach allows easy and dynamic creation of ViewModels and Views. Just create tree of ViewModels, for example in XML, and base on this create new functionality.
The questions are:
Is there any mvvm framework (mvvmcross, catel) supporting such approach for Xamarin.Forms?
How would you store tree of ViewModels - in XML, database tables, ...?
How would you create instances of ViewModels - deserialization, dependency injection, ...?
How to create Views and resolve (if framework does not support it)?
After some time I can share some experience about the questions I asked:
I do not know whether there is any mvvm framework supporting such approach. Probably Catel v5 is going to support this, but I did not checked this. I use custom solution.
In my solution I store ViewModels definitions in single database table in parent/child structure.
ViewModel instances are created by custom factories using definitions from database table.
Views are created using ValueConverters. It is possible, because each view has bindings created base on ViewModels structure.
Beside above answers I can suggest to use Prism. Although it has some disadvantages for me it is the best framework in such approach.
Yes! There's an MVVM Framework that fits exactly to what you are looking for and is created with Xamarin.Forms in mind:
FreshMvvM: https://github.com/rid00z/FreshMvvm
Quickstart Guide: http://www.michaelridland.com/xamarin/freshmvvm-quick-start-guide/
How does it compare to other options?
It's super light and super simple
It's specifically designed for Xamarin.Forms
Designed to be easy to learn and develop (great when you are not ready for RxUI)
Uses a Convention over Configuration
Features
PageModel to PageModel Navigation
Automatic wiring of BindingContext
Automatic wiring of Page events (eg. appearing)
Basic methods (with values) on PageModel (init, reverseinit)
Built in IOC Container
PageModel Constructor Injection
Basic methods available in Model, like Alert
Built in Navigation types for SimpleNavigation, Tabbed and MasterDetail
You can nest or derive ViewModels as much as you'd like (In our case we have a BaseViewModel). We have been using FreshMvvM for our startup and has been battle tested to work and fit to whatever we need.
Related
I've just created my first c# / XAML application using mvvmlight and I've tried to implement the MVVM pattern as best I can (WP8 app). However, I've slowly morphed my code in to a certain style and I don't think its correctly implementing the pattern! Any advice on how things are supposed to be would help enormously.
For example, using mvvmlight I am making heavy use of the ViewModelLocator. Some of my viewmodels get created right away, like the SettingsViewModel (there is a SettingsView).
SimpleIoc.Default.Register<SettingsViewModel>(true);
And then elsewhere in my project, my other viewmodels will directly access this viewmodel for occasional information via a property or a method... like this;
mySetting = ViewModelLocator.SettingsStatic.GetSomeSetting(var);
My concern is that my viewmodels are talking to each other in this way more and more. The issue with this is that they probably can't be tested independently now because they require or assume the existence of other viewmodels.
Any pointers here would be great!
EDIT: Another example is having a PersonView, and the PersonViewModel has some helper methods for UI display. In some cases I have other views that need to display this info.... and I use the viewmodellocator to get to them, rather than writing the helper methods again in the current viewmodel.
You are right in thinking that viewmodels being dependent on viewmodels is going to cause trouble. When I need to have access to "global" settings in my app, I use an interface that can be injected in the constructor of the view model. So, You can create an ISettingsService that contains the properties and methods you need. You also create a design time setting service that mimics or fakes the data/properties of the ISettingsService Interface
then in your view model locator you use this:
if (ViewModelBase.IsInDesignModeStatic) {
SimpleIoc.Default.Register<ISettingsService, DesignSettingService>();
} else {
SimpleIoc.Default.Register<ISettingService, SettingService>();
}
Create the DesignSettingService and SettingService which both implement the ISettingsService.
As for you vewmodels, the SimpleIOC will resolve/inject the required elements passed into the constructor of the class. If you have a class/viewmodel called MyViewModel and it wanted to use the settingsservice then you would define the constructor like this:
private ISettingsService _SettingsAccess;
public New(ISettingsService SettingsService)
{
_SettingsAccess = SettingsService;
SettingProperty= _SettingsAccess.GetProperty;
}
This keeps the viewmodels decoupled as this service is resolved in the constructor, that way you can change the implementation of your ISettingsService without breaking every viewmodel that uses it.
I use a INavigationService to handle all the navigation events in my app, this allows me to cancel navigation based on another viewmodels properties without needing the other viewmodel to be directly called/referenced by the current one.
One view model should never directly call another view model. Using this method you can pass as many "services" as are needed to the viewmodel. Every viewmodel I use gets a dataservice that connects to my model in addition to the navigationservice. Ie. A viewmodel that deals with people gets an IPeopleDataService where this service contains all the CRUD operations that affect the database. That way I can change the people objects in the database and service functions without having to change the people viewmodel as well.
I hope this helps.
I have been using the MVVM Light Toolkit to help learn the MVVM pattern. However, I have not been able to solve the problem of usercontrols within controls scenario.
For example, in a Timesheet application, lets say we have a control called NewUnitOfWork. When it first loads, a panel with a ListBox with a list of projects is loaded as the Content of the NewUnitOfWork. The user clicks on one. A new panel is swapped in with a ListBox containing the possible tasks for that project. A task is selected and a new panel is loaded which will contain controls to input data for the chosen task of the chosen project.
So, we have the selected item in one usercontrol being passed to the other two user controls, which are, in turn swapped in as the Content of the NewUnitOfWork control (or window).
If each control has its own ViewModel, we need to pass the selected value from one ViewModel to the next etc.
I have got it working in a single user situation using global variables (via a "service"). However, there are concurrency issues with that and it is not a good solution. It's sub-par.
I have seen many times the suggestion on this forum to have on ViewModel as a member of another ViewModel. Whilst this solves the problem at hand, I believe it is a violation of the MVVM pattern. Another ViewModel is not UI-related functionality that the ViewModel shoule be directly.
So. Has anyone found a clean MVVM-complying way to do this sort of thing?
Cheers
Please always keep in mind that MVVM is just a pattern and it is designed to help you separate your UI and logic. Do not be afraid to “violate the pattern” if it helps to increase testability or maintainability of the application.
Having a master ViewModel with several child ViewModels is very handy if you have a complex UI. The main ViewModel may be responsible for handling the top level UI controls and for coordination of the child VMs, while other ViewModels are responsible for communication with the sub regions of your UI.
Moreover, if you have a really complex UI with the multiple nesting UI layers, you can implement an infrastructure to automatically cascade all the events from master to child VMs.
And of cause, you may try to use one of the more advanced MVVM frameworks. For example Catel implements pretty comprehensive model to resolve such situations with nested VMs.
I don't see a problem with ViewModels referencing other ViewModels (based on my experience with TreeViews). Have a look at any article about TreeView and MVVM. You will see that each node is a ViewModel, that references a collection of child nodes, which are ViewModels. Trying to do that without VM-VM references would be a nightmare.
Josh Smith
http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx
I have been using the following setup:
A 'master' VM with a 'collection' VM and a 'details' VM as nested properties.
The master VM is tied to a View that is used as a master-detail form. This master-detail View is composed from two other Views.
I find it a very neat setup because it allows me to put search criteria in the master View(Model) and keeps the other View(Model)s clean.
I can't see how this would break the pattern.
I am trying to use CellTree, i am confused about placement of class implementing TreeViewModel, This class will need Collection of elements required to be rendered as tree if this is view type class i need to push collection from the presenter. If its a Presenter class i can directly call the server function and get the collection.
I am finding it more near to Presenter.... please sugget
According to GWT docs,
A key concept of MVP development is
that a view is defined by an
interface. This allows multiple view
implementations based on client
characteristics (such as mobile vs.
desktop)
So, looks like Presenter should know neither about data presentation widgets used in view implementation, nor about specific ViewModels and data providers used by these data presentation widgets (since data presentation widgets may be changed). ViewModels are generally coupled with particular way to implement data presentation, so I usually consider them as a part of View.
I usually create presenter methods like getObjectsList(params), which return array / list of required data, and then transform these results to ViewModel.
BTW, it would be great to hear other opinions :)
Should I register ViewModels in Container and resolve from there?
Benefits:
I can perform some actions when view model is activated
Container will inject dependencies for me
???
Drawbacks:
ViewModel lifetime management can be tricky:
if I make ViewModel singleton then I can't instantiate several controls of the same type
if I make ViewModel transient then I can easily end up in a situation of having several different instances when I actually expect same instance injected
???
What's the right answer?
I'd prefer to register if I could mitigate lifetime drawback.
I'm using Caliburn and Autofac if it matters.
A container is an ecosystem inhabited by the objects it creates. View models interact with those inhabitants and thus are also part of the ecosystem. To accurately reflect that relationship, you should register view models in the container.
You should always use InstancePerDependency with view models. A view model represents the state and behavior of a particular piece of UI - it is the non-framework-specific analogue of a control. Just as you can't generally place the same control instance in two locations in a UI tree, you can't also reuse the same view model instance.
If you could, we'd call it a ViewsModel :-)
The benefits of 2) is enough for me to let the container handle viewmodels. We're using our own MVVM framework where there is a strict one-to-one relationship between view instances and viewmodel instances. Thus, the 1) drawbacks are non-existent.
In cases where we need to share data between views, we accomplish this by injecting the viewmodels with a shared service instance.
Except from that, are there other circumstances where you expect one viewmodel instance to be shared among several views?
Not sure about autofac or Caliburn (might still apply) but when it comers to the Unity Container I will only register the ViewModel if...
I need to have it disposed of when the container is disposed of. You can create a lifetime manager that will store the newly created (non singleton) view model instance.
container.RegisterType<MyViewModel>(new DisposeableInstanceLifetimeManager());
...
container.Resolve<MyViewModel>(); // here all dependencies will get injected
...
container.Dispose();
If you want to share data I tend to create a sub (child) container and register the model as a singleton and have multiple view models share the same model.
var child = container.CreateChildContainer();
child.RegisterInstance(model, new ContainerControlledLifetimeManager());
child.Resolve<MyViewModel1>();
child.Resolve<MyViewModel2>(); // both can share the model instance
(Note: with Unity all dependencies are injected when using Resolve on the ViewModel even if it is not registered with the container).
Otherwise unless you need a singleton ViewModel (although I cannot think of when that would be useful) I feel adding the ViewModel to the container just adds more code for no benefit.
I have a singleton Model and ViewModel objects and would like to programmatically create and attach WPF views to them, one at a time. Views can be created dynamically, say by selecting a menu item (somewhere). Newly created view would dispose of any old view looking at a ViewModel. Then it would make itself a current view of that ViewModel, displaying it in some WPF window serving as a container for view UserControl. I am using MEF for IoC. It is important that Model and ViewModel objects are created only once. What would be the way to accomplish this using MEF?
You might have a look at the ViewModel and Writer sample applications of the WPF Application Framework (WAF). They show how to switch a view using MVVM and MEF.
I use viewmodel first approach in my testapps. so i instantiate viewmodel via mef and then wpf + datatemplates do the rest. all i have to do is binding my actual viewmodel to the contentcontrol.content.
you say that its important that ViewModel objects just created once. you achieve this with mef and creationPolicy.Shared or Lazy<> import. with this in mind i think ViewModel-First is the way you should go. its straightforward and you need no extra locator or wathever :)