How to use DI with WinRT - xaml

In a WinRT Page how can I inject dependencies?
I am thinking of doing something like this:
/// <summary>
/// A page that displays an overview of a single group, including a preview of the items
/// within the group.
/// </summary>
public sealed partial class MyPage : NSyncApplication.WinRT.Common.LayoutAwarePage
{
IMyDependency _myDependency;
public MyPage(IMyDependency myDependency)
{
_myDependency = myDependency;
this.InitializeComponent();
}
.
.
.
}
If this isn't a good practice please explain and recommend an alternative solution.
Note:
I don't need the specific DI containers that can be used with WinRT, that's been answered already and any idiot can look at nuget gallery and pick their choice.
This question is about how I can plug into the Page factory and inject my own dependencies. I have also looked at Prism for WinRT and that thing is even more convoluted than I remember the WPF version to be.
To repeat:
How can I inject into the page directly. Is there a page factory
or something that I can tap into to add custom instantiation code?
Should I inject to the code behind and make it a viewmodel? The Prism MVVM example had
another layer of abstraction for the ViewModel separate from the
code behind (which's considered part of the View). This is nice and cool, but requires more wiring and
custom mark ups than I care to do for my relatively simple project. I am hoping to roll with something more "light-weight". But may be there's an argument to be made against that, please explain.

Please, check MVVM-Light. They use VMLocator which exposes view models to which XAML can bind. On MSDN Magazine you can find an example of how to use it.

Related

ViewModels in ViewModelLocator MVVM Light

Is it correct to store all my ViewModels in SimpleIoc? For instance I am having three pages MainPage, Photos, Directories (therefore three ViewModels -> MainVM, PhotosVM, DirectoriesVM). Should I set DataContext in each page to View Model Property in ViewModelLocator or nest ViewModels as properties in MainVM and bind each page DataContext to Main.PhotosVMProperty, Main.DirectoriesVMProperty and so on? Could anyone explain me idea and purpose of IoC ?
First, lets look at what ViewModelLocator does and why we use it:
ViewModelLocator is declared as an object on our App.xaml page and is an application singleton. We're going to have one, and only one of them available to the application when it runs.
ViewModelLocator is the source for all our ViewModels in MVVM Light. For each ViewModel we'll have a property on the ViewModelLocator that allows us to get a ViewModel for a View. This code looks like this:
public class ViewModelLocator
{
public MainPageViewModel MainPage
{
get { return new MainPageViewModel(); }
}
}
This is a piece of my App.xaml:
<Application.Resources>
<vm:ViewModelLocator
x:Key="ViewModelLocator" />
</Application.Resources>
This is a piece from View.xaml
DataContext="{Binding MainPage, Source={StaticResource ViewModelLocator}}"
So far so good. To answer your first question, do you have to use Ioc in MVVM Light? No. There's no need as your viewmodel will be given to your view fully built and instantiated by the ViewModelLocator.
Now, onto your second question: What's the purpose of IoC?
IoC is designed to allow you to do the following:
With Mvvm Light you do the above like this:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main
{
get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
}
}
public class MainViewModel
{
public ObservableCollection<Foo> Foos { get; set; }
public MainViewModel(IDataService dataService)
{
_dataService=dataService;
Foos=_dataService.GetFoos();
}
}
When I resolve my MainViewModel when I call
SimpleIoc.Default.GetInstance<MainViewModel>()
what happens internally is that the SimpleIoc checks to see if the MainViewModel has any dependencies (parameters in its constructor). It then tries to resolve these parameters by looking at the interfaces that have been registered with it. It does this recursively, so if DataService had a dependency it would be instantiated and passed to the DataService constructor when it was being instantiated as well.
Why would I do all this work?
Make your classes easily unit testable
Make your code interface-driven. This means that you're referencing interfaces rather than concrete classes
Make your code loosely coupled. This means that someone can change the implementation of an interface and classes that consume that interface don't care and don't have to be re-coded.
Resolve your classes dependencies in an automated way.
In MVVM Light, you'll see that it can tell when it's running in design-mode (ViewModelBase.IsInDesignModeStatic), this means that you can create design-time services to provide your viewmodels data so your View in Visual Studio contains actual data.
MVVM Light has a lot of nice features but it appears to me that the Service Locator creates unwanted dependency of the views on the view models. Ideally, I would like to have the ViewModelLocator in Library A, the view models in Library B and the views in Library C. Then I can mix and match these as needed for future projects. However, in the design of MVVM Light, as far as I can see, the views (Library C) will always have a dependency on the ViewModelLocator (this is okay) but because the ViewModelLocator (Library A) will always have a dependency on the view models (Library B), then the views will always depend on the view models (this is not okay because a view now must include all the view model libraries it was ever used with across all products).
I believe that Prism gets around this problem by using string keys somehow. Am I missing something?
Oops! I think I just answered my own question. The solution is to make Library A, the ServiceLocator, specific to a particular solution (product). It then contains a reference to the view models only for that solution. Then the views depend on this ServiceLocator which in turn depends on all the view models for that product. The final result is that the views depend only on the views models that it will be used with for that product. There is no problem with thee fact that we are duplicating the ServiceLocator for each solution because this module contains only code that is specific to the solution. The components of the ServiceLocator such as the SimpleIoc class are, of course, common to all solutions, but these have been factored out into reusable classes that we invoke in ServiceLocator.
To summarize things, the problem I am trying to solve is suppose that a solution has 6 view models, four of which are closely related and two of which are closely related. We therefore create two assemblies, each containing the closely related view models. Suppose we design a product that uses one set of view models and the solution is designed to run Windows 8. Now the views are all different and we want to re-use only one set (assembly) of view models. So we just create a new ServiceLocator assembly that points to this assembly of view models and also any others that we need. Our new Windows 8 views now depend on this new ServiceLocator assembly and only the view models that are used in our new product (solution).

Use locator to manage multiple view-viewmodel pairs in Panorama Page

I'm new to Silverlight/MVVM. I tried some example of MVVM Light, it looks great.
For my scenario, I want to create a Panorama Page, for each Panorama Item, showing my usercontrol, a item list for a customer.
I've built usercontrol(view), viewmodel and WCF service model and works well in a single Panorama Item(Only use first customer).
Also, I use Locator of MVVM Light shown in MIX10 demo, it enables me to make design time data for Expression Blend.
My viewmodel will receive a parameter of customer ID then exchange data with WCF based on this ID.
And the customer list also comes from WCF. So I can't actually makes viewmodels in Locator's static constructor.
If viewmodels are built in runtime by calling Locator, how to make data binding?
The only way I think about is to make viewmodel object in usercontrol's constructor and make it datacontext.
Is there a better solution?
If you want to keep the same declarative model in the XAML, you can put a CurrentCustomerViewModel property on the locator and then set property to the right viewmodel before you navigate to the page.
Personally though for pages like that I typically put a viewmodel factory method on the locator (so it can cache them, etc) and call it from the OnNavigatedTo method, something like this.
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
string id = NavigationContext.QueryString["customerID"];
vm = ViewModelLocator.GetCustomerViewModel(id);
DataContext = vm;
base.OnNavigatedTo(e);
}
Then I just use Blend's sample data capabilities for design time data. This way also helps support pinning the page to the start screen since that will be the entry point to the app and I won't necessarily get a good chance to set the "CurrentCustomerVM" property anyway.

Dynamically changing the ViewModel of a View in an MVVM, MEF implementation

I have a usercontrol that i want to use throughout my Silverlight MEF MVVM solution.
I want to be able to link it up with one of a number of ViewModels depending on which module i am in. What this control does is list the records of a given entity so i can Add, Edit or Delete. I realized i would be using this control in multiple locations - to update several lookup tables, so i decided to make it's ViewModel dynamic. As seen below, I am using the Galasoft MVVM plugin.
if (!GalaSoft.MvvmLight.ViewModelBase.IsInDesignModeStatic)
{
// set DataContext
DataContext = PluginCatalogService.Instance.FindSharedPlugin(ViewModelTypes.ViewModelMT, PluginType.ViewModel);
_viewModel = (ViewModelMT)DataContext;
}
My question is how can i dynamically change from ViewModelMT to ViewModelCT to allow me to independently display lookup tables e.g. Maintenance Types and Contract Types on an instance of this same usercontrol? I took a look at the Viewmodel locator, but I'm still not sure how to get this done.
Thank you
I don't think this is really a ViewModel thing. It's more of a Service problem.
Your ViewModel for the control will not change but you'll dynamically slot in the required service to maintain your list. ie. MaintenanceTypeService and ContractTypesService will implement IListMaintenanceService which exposes an list of items and Add,Delete and Edit commands.

ShowDialog a RadWindow with MVVMLight

I have a functional MVVM patterned SL app with a RadWindow (essentially a ChildWindow), that I would like to remove the code-behind in my view that shows the window using its ShowDialog. Both the main view and the window is bound to the same ViewModel if that helps.
The button has both a ViewModel command using a MVVMLight RelayCommand to handle setting state as well as the event handler in the View.
The ultimate solution/pattern will be reused 20+ times so something better than code-behind would be great.
Thoughts?
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var window = new RadWindowTest.Controls.ChildWindow1();
window.Closed += new System.EventHandler<Telerik.Windows.Controls.WindowClosedEventArgs>(window_Closed);
window.ShowDialog();
}
In this case I would suggest you implement DialogService. This service you can inject into your view model, for testing you will have to inject an instance that does not depend on the view, thus maintaining testability. You can use the ViewModelLocator to make this service available to your application.
Another approach would be to implement a ViewBase class that implements an interface that allows you to display the dialog. This interface is now used by the ViewModel to display a dialog. Again to test you need to provide a different implementation of the interface. A sample can be found here.
Both ideas revolve around the same concept of factoring out the function that shows the dialog. In order to strictly de-couple the View and the ViewModel you will have to think about how the ViewModel specifies which dialog has to be shoen, and how the dialog resut or dialog model is returned to the calling ViewModel.
Which approach is better is open to your judgement. Personally I prefer the first approach as I do not have to inherit the views from a common base class.
PS: Use a command to get to the point in your ViewModel where you want to show the dialog. Using a dialog service should need no code behind.

Implicit DataTemplate equivalent for Silverlight + Prism

I'm building an Silverlight application which consists of a grid containing multiple different widgets. Each widget is implemented as a ViewModel class which are then binded to grid.
With WPF I'd use implicit DataTemplates to bind certain ViewModel to a certain View. But since Silverlight doesn't support this feature I'm a bit stuck.
So far I've only thought of implementing some sort of global DataTemplateSelector to which each Prism module would register matching ViewModel and View pairs at startup. Then I could use Unity to inject this selector to grid and achieve what I want but this doesn't feel like the best way to do it.
Any ideas how should I do this?
I did some more googling and found few articles about TemplateContentControl (e.g. http://blogs.microsoft.co.il/blogs/arielbh/archive/2010/10/24/how-to-develop-mvvm-silverlight-applications-with-prism.aspx) and after some testing it seems to be just what I was looking for.
Check out the DataTemplateSelector for Silverlight.
Read about it more here.