Simple Dependency Injection with XAML

1/17/2011 5:01:25 PM

Update: Channel 9 video in case you don’t want to read the article.

Download demo code here

Let’s start by painting a simple scenario:  I have a ViewModel that lists a collection of data items.  Let’s say a list of Tweets based on a given hash tag search.  The ViewModel has a SaveCommand that I will wire into my view.  When the user causes the SaveCommand to execute, the ViewModel will leverage some service to persist the selected tweet to some form of storage.  And there is the rub…  Maybe in v1, I will save that tweet in IsolatedStorage, but in the future, I will want to also provide an option to select a cloud-based storage solution.  This is is where we start to hear all kind of things about Dependency Injection, IoC, and more. 

Hey, I am a fan of Dependency Injection and using in IoC container, but the what I hate about DI/IoC is that is takes me away from the pure XAML-based goodness of defining my ViewModel in XAML view an element’s DataContext and into the world of code-behind and setting things up with code. I would much rather do this in MainPage.xaml

<UserControl.DataContext>
     <nScreenLibrary_ViewModels:SearchViewModel/>
</UserControl.DataContext>

than have to start resorting to this in my MainPage.xaml.cs code-behind file…

this.DataContext = new SearchViewModel();
Obviously this is a simple example that does not use DI or an IoC.  Things would be much more complicated as I would need to configure the IoC, call into the IoC to get the correct instance of a ViewModel, and then assign that to my DataContext. I would really like to be able to stick to a XAML-based solution for configuring my application to use different storage providers without having to resort to using code-behind, picking an IoC, etc.  While the DI/IoC route may be needed for complex scenarios, a lot of applications only need a simple solution.

That brings us to using XAML to accomplish a version of Property-based Dependency Injection.  By no means am I saying this solution is perfect.  But I think it will work for a lot of people.  There really is no rocket science here, but if you are still new to XAML and haven’t explored a lot of its power, this may prove a useful solution.  In addition, as I searched around the Intertubes for a similar approach, I couldn’t find one which means I am either blazing a trail that will prove beneficial to many, or I am so far off the reservation that the Developer Police will be coming to take me away shortly.

That brings us to the solution.  Suppose I have a ViewModel that looks something like this

    public class SearchViewModel :BaseViewModel
    {
        public ObservableCollection<MyDataItem> SearchItems{ get; set; }
        public ICommand SaveCommand { get; set; }
        private IFavoritesService _favs;
        public SearchViewModel() : base()
        {
            this.Tweets = new ObservableCollection<Tweet>();      
        
            this.SaveCommand = new RelayCommand()
            {
                CanExecuteCommand = (tweet) => { 
                    var saveTweet = tweet as Tweet; 
                    return saveTweet != null;
                },
                ExecuteCommand = (tweet) => {
                    var saveTweet = tweet as Tweet;
                    if (saveTweet != null)
                        _favs.Save(CurrentSearchTag, saveTweet);
                }
            };
        }
    }

As you can see from the code, the SearchViewModel will use some implementation of IFavoritesService in the SaveCommand’s ExecuteCommand property.  Let’s say that I have a concrete implementation of that service that would look something like this…

public class IsolatedStorageFavs : IFavoritesService
{
    public void Save(string searchTag, Models.Tweet tweet) {
          // do some saving
    }
}

How do I get the IsolatedStorageFavs object into the SearchViewModel without using some kind of DI/IoC and code-behind solution?  The answer is surprisingly simple.

First, let’s update our SearchViewModel implementation by adding a FavoritesStorage property as shown below

public class SearchViewModel : BaseViewModel
{
     private IFavoritesService _favs;
     public IFavoritesStorageService FavoritesStorage {
          get { return _favs; }
          set { _favs = value; }
     }
}

You could simple replace the private _favs member with an automatic property as well… it’s up to you but I wanted to show how to modify the existing example.  With that change, we can now modify our XAML as shown below:

<UserControl.DataContext>
     <nScreenLibrary_ViewModels:SearchViewModel>
         <nScreenLibrary_ViewModels:SearchViewModel.FavoritesStorage>
             <nScreenLibrary_Services:IsolatedStorageFavs/>
         </nScreenLibrary_ViewModels:SearchViewModel.FavoritesStorage>
     </nScreenLibrary_ViewModels:SearchViewModel>
</UserControl.DataContext>

Now, when the application is run, an instance of IsolatedStorageFavs will be created automatically and assigned to the SearchViewModel’s FavoritesStorage property.  If at a later date I wanted to swap in a cloud-based storage solution, I could just go back to my MainPage.xaml file and replace the XAML with the correct markup to instantiate a CloudStorageFavs, for example.

The one drawback is that  you are limited to Property-based Dependency Injection.  If you need access to the property during construction of your ViewModel, this will not work since Silverlight/WPF will not assign the property an object until after construction is complete.  Another one, though not a big deal IMHO, is that if you are not comfortable working with XAML, adding namespaces, etc. then you may want to stick to doing this kind of thing in code.  I feel, however, that this is much simpler thing to learn than diving into DI/IoC if you have not done that before.

Tags:

Silverlight | XAML | Screencasts

Comments are closed

Powered by BlogEngine.NET 1.6.0.0
Theme by Mads Kristensen

About the author

Jeff Brand Jeff Brand

This is the personal web site of Jeff Brand, self-proclaimed .NET Sex Symbol and All-Around Good guy. Content from my presentations, blog, and links to other useful .NET information can all be found here.

E-mail me Send mail


Calendar

<<  July 2014  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar

My Twitter Updates

XBOX
Live

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2014

Sign in