Spaghetti Code Podcast–January 2010

1/31/2011 9:06:34 AM

Spaghetti Code hosts Jeff Brand and Adam Grocholski discussing events in the world of .NET development and beyond. After a long holiday break, the Adam and Jeff cover a wide range of news in the world of .NET development. Topics include a range of technologies from Web Matrix family of products to Surface 2.0.  Get caught up with the the latest headlines in the .NET Church of What’s Happening Now.

Tags:

Headlines

Implementing MVVM Message Routing with XAML

1/20/2011 8:51:18 AM

Watch the Channel 9 video here

Download Source Code

If you have worked with MVVM for any period of time, you will find yourself in a situation where you have multiple ViewModels being used on a single page of your application.  Regardless of why you have multiple ViewModels, the challenge of coordinating activity between them is the same: how do I get a ViewModel A to react to some action taken in ViewModel B.  The classic example of this would be you have a ViewModel called CustomerListViewModel that is responsible for working with a View to search for and list customers from a database or web service.  When the user selects a customer, you want another ViewModel, let’s call this one OrdersViewModel, bot be notified and as a result, display all of the orders associated with a the selected customer.

There are lots of approaches to doing this.  PRISM uses the EventAggregator.  For a lot of apps, I lean towards a simpler implementation, similar to the one described by Brent Edwards here.  A lot of times, once you start investigating using some kind of messaging solution, the problem of wiring up the “message bus” with the ViewModels will raise it’s somewhat ugly head.  A lot of solutions rely on either a DI/IoC solution or maybe on some application-wide “service” to provide a messaging capability.  The problem with first approach is that you have to understand DI/IoC (not a bad thing necessarily) and you have to pick an IoC (lots of choices and if you are doing nScreen not all of them work everywhere so you have to be prudent with your choices).  The second solution can be tricky since you have to worry about how the ViewModels subscribe and publish with the service, and more importantly, that ViewModels unsubscribe when they no longer need the service.

When I was looking at this problem for the project I am working on, I had a few things I took into consideration and by doing so I was led to the solution I am about to show you.  First, I was building a multi-screen solution, or nScreen.  This meant that my app would be running in the browser, out of the browser, and on Windows Phone 7.  This necessitated that I look at my ViewModels as potentially the only ViewModel on a given page or I could have multiple ViewModels on a page.  This meant that from one implementation to another, a given ViewModel may or may not need to publish/subscribe to the message bus. Secondly, because I was building for nScreen, and I wanted anyone to be able to use what I was building as a template for their own nScreen solutions, I really didn’t want to dictate going the DI/IoC route if I didn’t have to.  Lastly, I wanted to make using the message bus as easy as possible, especially for people that may be working with the

In most cases, I feel that when dealing with multiple ViewModels on a single “page”, the message bus only needs to exist for the lifetime of that page and that having an application-wide service is not needed.  With that in mind, here is the approach I used for my project.

First, I used the same IMessageBus solution that Brent talks about in his blog.  As with most MVVM frameworks, I had implemented a BaseViewModel class that was the foundation for each of my ViewModels.  The first thing I did was add a MessageBus property to my BaseViewModel class

private IMessageBus _messageBus;
public IMessageBus MessageBus
{
    get { return _messageBus; }
    set
    {
        if (_messageBus != null)
           Unsubscribe();
        _messageBus = value;
           Subscribe();
    }
}

Now you are probably asking why am adding the MessageBus as a Property.  I don’t want to have to write code in my code-behind to wire up a message bus object for a given page to the various ViewModels, either directly or using some other mechanism like an IoC Container.  This enables me to use the property to configure message passing on a page using something similar to Property-based Dependency Injection.  So how do I do that?  Let’s start by looking at a sample MainPage.xaml.

<UserControl>
    <Grid x:Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>
    </Grid>
        <Grid x:Name="CustomerGrid">
            <Grid.DataContext>
                <MessageBusDemo_ViewModels:CustomerListViewModel/>
            </Grid.DataContext>
        </Grid>
        <Grid x:Name="OrdersGrid">
            <Grid.DataContext>
                <MessageBusDemo_ViewModels:OrdersViewModel/>
            </Grid.DataContext>
        </Grid>
</UserControl>

I have two Grids on the page, each with their DataContext set to a different ViewModel.  I would like the CustomerListViewModel to publish messages to the MessageBus whenever a customer is selected, and have the OrdersViewModel subscribe to those messages so it can display orders for the selected customer.  To make this happen, I need to have an instance of the MessageBus available on this page that both of the ViewModels are aware of.  I have a couple of different options for getting the MessageBus created.  In Visual Studio, I can just add an object resource to the page’s Resource collection as shown below:

<UserControl.Resources>
     <MessageBusDemo_Core:MessageBus x:Key="MessageBus"/>
</UserControl.Resources>

In Visual Studio, you need to do this by hand in the XAML.  If you are using Expression Blend, you can also do it by hand, or you can use the Data tab and select Create Object Data Source and select the MessageBus class from the Create Object Data Source dialog.  I then like to go in and remover the  d:IsDataSource="True" attribute from the resulting XAML since the MessageBus object is really not a data source and it makes the data binding we are about to do a bit more natural.  That’s just my opinion.

Once I have added the the MessageBus to my XAML, I can now wire up the various ViewModels to the MessageBus using data binding.  In Visual Studio, this is again all done by hand editing the XAML.  But if I am using Expression Blend, this all becomes a wonderfully easy point and click exercise.  For each Grid, use the Property editor to select the DataContext property and create a New data context and pick the appropriate ViewModel class.  Then, use the drop arrow to reveal the properties on the ViewModel.  Select the MessageBus property and using the Advanced Options square, choose Local Resource and pick the MessageBus.  Bang!  You have now wired up the ViewModel to the MessageBus.  Check out the Channel 9 video I recorded that walks you through this entire entire article to see how it all works.

From there, your ViewModels can now call MessageBus.Publish or MessageBus.Subscribe as needed.  Because the MessageBus property is set post-construction, you will not be able to setup your subscriptions when the object is instantiated. 

You can then use the Subscribe method to setup all of the required subscriptions when a MessageBus is available to your ViewModel.  On the BaseViewModel, just set up some virtual methods that you can override in each of your own derived ViewModel classes.  That is why the property definition on the BaseViewModel includes calls to a Subscribe() and UnSubscribe() method.  There are virtual methods on the BaseViewModel…

public virtual void UnSubscribe() { }
public virtual void Subscribe() { }

In your derived ViewModels, all you need to do is override these two methods so that your ViewModels will automatically Subscribe/Unsubscribe with the MessageBus.  Here is an example of how it is down in the OrdersListViewModel in the demo application

protected override void Subscribe()
{
    MessageBus.Subscribe<Customer>(GetOrdersForCustomer);
}
protected override void Unsubscribe()
{
    MessageBus.Unsubscribe<Customer>(GetOrdersForCustomer);
}

I’m noodling on a way provide an interactive design experience for the MessageBus using XAML, allowing you to configure ViewModel’s subscriptions in XAML as well.  I have a few ideas, but need to explore them in more detail at a later time.

Tags:

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

MultiScreen Development with Microsoft Technologies Content Available

1/13/2011 1:21:56 PM

Here are links to the slides and demo code to the Multiscreen Development with Microsoft technologies webcast I did today. Look for some Channl9 videos starting soon that will go through the different parts in more detail.

PresentationDemo Code

Tags:

Headlines | Windows Phone | XAML

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

<<  April 2014  >>
MoTuWeThFrSaSu
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

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