Yet another way to attach ViewModels to Views

Throughout the short history of the MVVM design pattern, several methods have originated for populating Views with their ViewModels.  One of the most common methods is to use one of the frameworks (PRISM, MVVM Light, Jounce, among others).  Typically, the ViewModel is registered with an IOC container and retrieved when needed.   One of the more outstanding issues is when to take the ViewModel and assign it to a View’s DataContext.  In many cases, the connection occurs in the constructor of the View with the View requesting the ViewModel from the IOC container.  In other cases, a locator is used as a static resource in the View’s Xaml, and using DataBinding a property of the locator is bound to the DataContext.  In the latter case, the locator requests the ViewModel from the IOC container.

In a recent project, I discovered (or rediscovered) another method for binding a ViewModel to a View.   Using Unity’s IOC Container, I registered both the View and the ViewModel together.  Granted this method will not work for every scenario, but in the cases where you create Views programmatically, I believe this method works perfectly.

Unity will allow you to register a type with a key which becomes important when registering different configurations of the same type.   But  more importantly, Unity supports configuration via InjectionProperties (and other methods as well).  InjectionProperties will enable Unity to resolve your Type and inject additional values into the generated class.  InjectionProperties work like this:

   1: int expectedInt = 8;
   2: container.RegisterType<MyClass>(
   3:     new InjectionProperty("IntProperty", expectedInt));

Basically, Unity will create an instance of MyClass and set the property “IntProperty” to 8, when the container resolves the type.

For a View to be registered with its ViewModel, several steps must be taken .  The steps are simple, first register the ViewModel with Unity, then register the View with an InjectionProperty, optionally adding a key if you need to register the view multiple times with different configurations.

   1: public void RegisterDialog<TView, TViewModel>(string dialogName)
   2:     where TView : IDialogView
   3:     where TViewModel : IDialogViewModel
   4: {
   5:     if (string.IsNullOrEmpty(dialogName)) throw new ArgumentNullException("dialogName");
   6:
   7:     if (!_container.IsRegistered<TViewModel>())
   8:         _container.RegisterType<TViewModel>();
   9:
  10:     _container.RegisterType<IDialogView, TView>(dialogName,
  11:         new InjectionProperty("DataContext", new ResolvedParameter<TViewModel>()));
  12: }

In the code above, I geared the method to support some dialogs, but it’s easily modified to support any type of view you’d like.  I use Unity’s ability to name the registrations so I can register multiple views of the same type but with different ViewModels.  One item to note is the use of the ResolvedParameter class.  The ResolvedParameter instructs Unity to only create the type when it is requested.  If I “newed” up a ViewModel instead, Unity would keep around an instance of the ViewModel to inject into all resolved views.

In my Bootstrapper.cs file, where you’d normally register your classes in an IOC container,, I simply make calls to this method for any dialogs I want to create in the application.

   1: RegisterDialog<DialogView DialogViewModel>(DialogNames.OkCancelDialog);
   2: RegisterDialog<DialogView, LoginDialogViewModel>(DialogNames.LoginDialog);

Here I am registering two dialogs of type DialogView with two different ViewModels and assigning them a key.  Now, it’s trivial to gain a reference to them in the application:

   1: if (!this.User.IsLoggedIn) {
   2:     IDialogView dialog = _dialogContainer.Resolve<IDialogView>(DialogNames.LoginDialog);
   3:     dialog.Show();
   4: }

That’s all there is to it.  Of course, I’ll leave the whole Dialog framework implementation up to you.

Unity is a complex framework with many features.  InjectionProperties are only one tool to enhance the configuration of your registrations.  Unity will even allow you to call a method on your object when it’s instantiated with or without parameters.

Sergio Loscialo

View Comments

Recent Posts

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

5 days ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

1 month ago

Mastering Compliance: The Definitive Guide to Managed Compliance Services

In the intricate landscape of modern business, compliance is both a cornerstone of operational integrity…

2 months ago