Posted by: dotnetninja | February 23, 2010

IOC (Inversion Control) With XAML

Today I have read an post about IOC and XAML or how to use IOC with XAML. Original post was on Rob Relyea’s blog with a couple of links to other approaches and resources. In that post there was nothing about MVVM (model view view model) and my first thought was to somehow use IOC to bind my viewmodels to the source in XAML.

After searching the web I did not found anything simple and straight forward to use. So that leads me to create something “simple” and possible useful.

Basic idea is to bind DataContext of the View to the ViewModel contract. Something like this, and magically resolve correct viewmodel implementation.

<UserControl x:Class="Module2.Views.LogListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodels="clr-namespace:ModuleA.Log.ViewModels;assembly=ModuleA">
<UserControl.DataContext>
<viewmodels:ILogListViewModel/>
</UserControl.DataContext>
...
<Grid>
        <ListBox ItemsSource="{Binding ApplicationLogs}">
...

Simplest way to do this is to create an Converter (IValueConverter), bind source to the interface and resolve the implementation by using the converter.

public class ViewModelResolverConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {

      if (value == null)
        throw new ArgumentNullException("value");

      IUnityContainer unityContainer = Module.MyContainer;

      var typeToResolve=Type.GetType(value.ToString());
      if(typeToResolve==null)
        return DependencyProperty.UnsetValue;

      var resolvedViewModel = unityContainer.Resolve(typeToResolve);
      if(resolvedViewModel == null)
        return DependencyProperty.UnsetValue;
      return ret;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      throw new NotImplementedException();
    }
  }

In this case I am using Unity from Microsoft pattern and practices but you could use any type of the IOC.

ViewModel could look something like this

public partial class LogListAViewModel:BaseViewModel, ILogListViewModel
  {
    public LogListAViewModel()
    {
       ...
    }

    private bool _isSelected = false;
    public bool IsSelected
    {
      get { return _isSelected; }
      set
      {
        if (_isSelected != value)
        {
          _isSelected = value;
          OnPropertyChanged(()=>IsSelected);
        }
      }
    }
    public string Info
    {
      get { return "Log View"; }
    }
...
  }

And finally XAML

<UserControl x:Class="Module2.Views.LogListView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:converter="clr-namespace:ModuleA.Converters"
xmlns:viewmodelscontracts="clr-namespace:ModuleA.ViewModelContracts;assembly=ModuleA">
<UserControl.Resources>
<converter:ViewModelResolverConverter x:Key="viewModelConverter"/>
</UserControl.Resources>
<UserControl.DataContext>
<Binding Source="{x:Type viewmodelscontracts:ILogListViewModel}"
             Converter="{StaticResource viewModelConverter}" />

</UserControl.DataContext>
...
<Grid>
        <ListBox ItemsSource="{Binding ApplicationLogs}">
...

As the final word, I prefer use binding view to viewmodel mainly to not end with application that is unpredictable, too loosely coupled and fragile, but in some cases this could be useful.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: