In this post, i’ll describe how we evolved to Binder abstraction, step-by-step and on the way talk about other useful abstractions that help alleviate the problem of coupling.

Trading System Scenario: On the Pricing Grid, each instrument receives prices updates, user can click on either Buy or Sell column for an instrument in the grid and it pops up a TradeTicket (a Window). This Trade ticket has few fields like the Instrument Code, Side, Price (that keeps updating as the instrument ticks), quantity (a user entered field) and finally a button to submit the trade.

Lets say, the TradeTicket view is defined by the XAML below and it is backed by TradeTicketViewModel.

<Window x:Class="TradingApplication.Views.TradeTicket"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Trade Ticket"
    Name="tradeTicketWindow"
    Height="285"
    Width="300">

    <Window.Resources>
        <DataTemplate x:Key="ttvm" DataType="{x:Type ViewModels:TradeTicketViewModel}">
        </DataTemplate>
    </Window.Resources>
    <Grid DataContext="{StaticResource ttvm}">
</Window>

Here is the TradeTicketViewModel class.

public class TradeTicketViewModel : Notifier
{
  private readonly ITradingService tradingService;
  private readonly InstrumentUpdateEvent instrumentUpdateEvent;
  private Instrument instrument = Instrument.Empty;
  private double price;
  private Side side;

  public TradeTicketViewModel(ITradingService tradingService, IEventAggregator eventHub)
  {
    this.tradingService = tradingService;
    instrumentUpdateEvent = eventHub.GetEvent&lt;InstrumentUpdateEvent&gt;();
    instrumentUpdateEvent.Subscribe(OnPriceUpdateReceived);
  }

  public bool AsReadOnly { get; set; }
  public int Quantity { get; set; }
  public string InstrumentCode { get; set; }
  public Side Side { get; set; }

  public double Price
  {
    get { return price; }
    set
    {
      price = value;
      RaisePropertyChanged("Price");
    }
  }

  public ICommand SubmitTrade
  {
    get
    {
      return new RelayCommand(Execute, CanExecute);
    }
  }

  public ICommand QuantityEntered
  {
    get
    {
      return new ValidationCommand(AssignValidQuantity);
    }
  }

  private void AssignValidQuantity(object incomingQuantity)
  {
    int quantity;
    var isValidQuantityType = int.TryParse(incomingQuantity.ToString(), out quantity);
    var isValid = isValidQuantityType && IsValidQuantity(quantity);

    if (isValid)
    {
      Quantity = quantity;
      return;
    }
  }

  private bool IsValidQuantity(int quantity)
  {
    return quantity > 0;
  }

  private bool CanExecute(object obj)
  {
    return IsValidQuantity(Quantity) && !AsReadOnly;
  }

  public void Execute(object obj)
  {
    var trade = new Trade(Side)
    {
      Price = Price,
      Quantity = Quantity,
      InstrumentCode = InstrumentCode
    };
    tradingService.Submit(trade);
  }

  private void OnPriceUpdateReceived(Instrument instrument)
  {
    if(AsReadOnly)
    {
      return;
    }

    if (insrument.Code.Equals(InstrumentCode))
    {
      this.instrument = instrument;
      Price = GetPrice(instrument);
    }
  }

  private double GetPrice(Instrument instrument)
  {
    return (side == Side.Buy) ? instrument.Bid : instrument.Ask;
  }
}

Here is the Notifier implementation

public abstract class Notifier : INotifyPropertyChanged
{
  public event PropertyChangedEventHandler PropertyChanged;

  protected void RaisePropertyChanged(string propertyName)
  {
    if (PropertyChanged != null)
    {
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
 }
}

Please refer to this article on the MSDN site for RelayCommand. Here is the ValidationCommand Implementation:

public class ValidationCommand : ICommand
{
  private readonly Action<object> callback;

  public ValidationCommand(Action<object> callback)
  {
    this.callback = callback;
  }

  public void Execute(object parameter)
  {
    callback.Invoke(parameter);
  }

  public bool CanExecute(object parameter)
  {
    return true;
  }

  public event EventHandler CanExecuteChanged;
}

The XAML above will create the ViewModel instance at View Level. The Trading Service and Event Aggregator, lets say are Singleton-ish within the application and so the DataTemplate defined at the TradeTicket view level will not help much. Also, XAML requires a parameterless constructor on TradeTicketViewModel, but what we have is a parameterized constructor that takes in two collaborators

  • Trading Service for submiting trades
  • and Event Aggregator to receive price updates for that instrument

One option is to use the setter in the XAML. But good OO design principles tell us to inject the dependent collaborator without whom the object cannot function during object creation and not inject via setter. So, lets rule out the setter option.

So, the next option is to move the DataTemplate, at a higher level, say application level where we can access and set these collaborators. There are two ways in which this can be done. One is to define it inline within in the Application XAML and have that ViewModel available to the entire application.

<Application x:Class="TradingApplication"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <!-- This is will create the ViewModel instance at Application Level and not View Level -->
        <DataTemplate x:Key="ttvm" DataType="{x:Type ViewModels:TradeTicketViewModel}" />
    </Application.Resources>
</Application>

Another is to use the Resource Dictionary (this will be residing in a external file). This is also helpful when you want to share resources across applications (a rare re-use scenario for ViewModels atleast, for Styles, Themes its understandable). Resource Dictionary is a XAML based file and it will contain the above DataTemplate definition

<Application x:Class="TradingApplication"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <ResourceDictionary Source="filePath" />
    </Application.Resources>
</Application>

However, Resource Dictionary is primarily intended to instantiate viewy stuff like Themes, Shaders etc… and not instantiate Models for Views (avoid mixing concerns). So, inside XAML, you really don’t want to:

  • create view model instances
  • and bind view model instances to view

So, Application XAML and Resource Dictionary are ruled out as well. What is another place where you could instantiate ViewModels? Lets take a look at the possibility of using the XAML Code Behind, where we can create the ViewModel and bind the Data Context. In there, one could do the following:

public partial class TradeTicket : Window
{
  public TradeTicket()
  {
    InitializeComponent();
    ITradingService tradingService = //Get Reference from somewhere
    IEventAggregator eventHub = //Get Reference from somewhere
    //Bind the DataContext here.
    DataContext = new TradeTicketViewModel(tradingService, eventHub);
  }
}

But, from a pure MVVM perspective, you really don’t want to see any non-View related stuff happening in the Code Behind. The only view-related stuff is, InitializeComponent(), whereas rest is creation of the ViewModel, getting references to the collaborators, injecting them in the ViewModel and finally binding to the DataContext.

So, we need to move this out from here, but where? It would be nice, if I have some abstraction like ApplicationContext and tell it to create a fresh instance of the ViewModel whenever required. It is the responsibility of the ApplicationContext to create and wire up the collaborators and dole out a fresh ViewModel instance when asked for. Here is how the above code would then look like:

public partial class TradeTicket : Window
{
  public TradeTicket()
  {
    InitializeComponent();
    //Bind the DataContext here.
    DataContext = ApplicationContext.Instance.Get<TradeTicketViewModel>();
  }
}

Here is the Application Context code. In my case, the ApplicationContext is based on Unity IoC, alternatively, you could use Spring.NET as your IoC container.

public class ApplicationContext
{
  private readonly IUnityContainer unity;
  private static readonly ApplicationContext instance = new ApplicationContext();

  public static ApplicationContext Instance
  {
    get
    {
      return instance;
    }
  }

  private ApplicationContext()
  {
    unity = new UnityContainer();
  }

  public void RegisterType<TType, TImpl>(Scope scope) where TImpl : TType
  {
    unity.RegisterType<TType, TImpl>(GetLifetimeManager(scope));
  }

  public void RegisterType<T>(Scope scope)
  {
    unity.RegisterType<T>(GetLifetimeManager(scope));
  }

  public void RegisterInstance<T>(T anObject, Scope scope)
  {
    unity.RegisterInstance(typeof(T), anObject, GetLifetimeManager(scope));
  }

  public void RegisterInstance<TType, TImpl>(TImpl anObject, Scope scope) where TImpl : TType
  {
    unity.RegisterInstance(typeof(TType), anObject, GetLifetimeManager(scope));
  }

  public TType Get<TType>()
  {
    return unity.Resolve<TType>();
  }

  public Dispatcher GetApplicationDispatcher()
  {
    return Application.Current.Dispatcher;
  }

  private LifetimeManager GetLifetimeManager(Scope scope)
  {
    switch (scope)
    {
      case Scope.Singleton:
        return new ContainerControlledLifetimeManager();

      case Scope.Prototype:
        return new TransientLifetimeManager();

      case Scope.Request:
        return new PerThreadLifetimeManager();
    }
    throw new ArgumentException(string.Format("Undefined Lifetime Scope: {0}", scope));
  }
}

ApplicationContext can be be instantiated at the Application level, in the application code behind. Take a look at the creation of ApplicationContext and registration of types with it.

public partial class TradingApplication : Application
{
  private ApplicationContext appCtx;

  public TradingApplication()
  {
    //Create Application Context Instance
    appCtx = ApplicationContext.Instance;
  }

  protected override void OnStartup(StartupEventArgs e)
  {
    RegisterMainView();
    RegisterInfraStructureServices();
    RegisterViewModels();
    RegisterViews();
  }

  private void RegisterMainView()
  {
    appCtx.RegisterType<MainView>(Scope.Singleton);
  }

  private void RegisterViewModels()
  {
    appCtx.RegisterType<TradeTicketViewModel>(Scope.Prototype);
  }

  private void RegisterViews()
  {
    appCtx.RegisterType<TradeTicket>(Scope.Prototype);
  }

  private void RegisterInfraStructureServices()
  {
    appCtx.RegisterType<IEventAggregator, EventAggregator>(Scope.Singleton);
    appCtx.RegisterType<IBinder, ViewViewModelBinder>(Scope.Singleton);
    appCtx.RegisterType<ITrader, Server.Trading.Service.Trader>(Scope.Singleton);

    var tradingService = new TradingService(clientId, appCtx.Get<ITrader>());
    appCtx.RegisterInstance(tradingService, Scope.Singleton);
  }
}

So far so good, we have been able to move out the creation and wiring business to the ApplicationContext, we still have to get rid of the last line; binding to the DataContext.

Now, lets think how a user would perform a trade; pricing grid is the place where user will click on instrument row (either on the Bid or the Ask cell) and we should be able to pop-up a TradeTicket Window that is backed by the TradeTicketViewModel. The user then enters the quantity and hits Submit button to make a deal. For the user to do this effectively, we should show some of the instrument details on the ticket, that is, bind the row data, like the Instrument Code, Side and Price (current and continue to refresh updates) to the TradeTicket view’s DataContext to be displayed on the View.

Clearly there are many things involved here:

  • Passing Data from Grid row to View
  • Initialize required properties on ViewModel from row data.
  • Bind the view DataContext to the ViewModel
  • Finally, show the view.

In the current context of discussion, two items are of importance to us, i.e., Bind required properties on to ViewModel and finally bind the View’s DataContext to the ViewModel. This calls for a role of Binder that can own that responsibility. Here is the what the Binder can do:

public interface IBinder
{
  TViewModel Bind<TView, TViewModel>(ref TView view) where TView : FrameworkElement;
  TViewModel Bind<TView, TViewModel>(TView view, TViewModel viewModel) where TView : FrameworkElement;
  IBinder Bind<TTarget, TProperty>(TTarget target, Expression<Func<TTarget, TProperty>> propertyOrField, TProperty data);
}

Here is the concrete implementation of the Binder.

public class ViewViewModelBinder : IBinder
{
  private readonly ApplicationContext appContext = ApplicationContext.Instance;

  public TViewModel Bind<TView, TViewModel>(ref TView view) where TView : FrameworkElement
  {
    if (view == null)
    {
      view = appContext.Get<TView>();
    }
    var viewModel = appContext.Get<TViewModel>();
    return Bind(view, viewModel);
  }

  public TViewModel Bind<TView, TViewModel>(TView view, TViewModel viewModel) where TView : FrameworkElement
  {
    view.DataContext = viewModel;
    return viewModel;
  }

  public IBinder Bind<TTarget, TProperty>(TTarget target, Expression<Func<TTarget, TProperty>> propertyOrField, TProperty data)
  {
    SetPropertyOrFieldWithData(target, propertyOrField, data);
    return this;
  }

  private void SetPropertyOrFieldWithData<T, TProperty>(T t, Expression<Func<T, TProperty>> propertyOrField, TProperty data)
  {
    var propertyExpression = propertyOrField.Body as MemberExpression;

    if (propertyExpression == null)
    {
      throw new ArgumentException("Expecting Property or Field Expression of an object");
    }
    var targetExp = Expression.Parameter(typeof(T), "target");
    var propertyExp = Expression.PropertyOrField(targetExp, propertyExpression.Member.Name);
    var valueExp = Expression.Parameter(propertyExpression.Type, "value");
    var assignExp = Expression.Assign(propertyExp, valueExp);
    var expression = Expression.Lambda<Action<T, TProperty>>(assignExp, targetExp, valueExp);
    var assignPropertyValueTo = expression.Compile();
    assignPropertyValueTo(t, data);
  }
}

Now, the Binder can be used it like this:

var binder =
 new ViewViewModelBinder>TradeTicket, TradeTicketViewModel>()
    .Bind(vm => vm.InstrumentCode, row.InstrumentCode)
    .Bind(vm => vm.Side, row.Side)
    .Bind(vm => vm.AsReadOnly, false);

By evolving this ViewViewModelBinder, we do not need any DataContext binding in the View now. Thus the, TradeTicket code behind will now be just reduced to

public partial class TradeTicket : Window
{
  public TradeTicket()
  {
    InitializeComponent();
  }
}

Phew! That was quite a long post, but it did not make sense to split it in to many. There are other interesting abstractions that I will cover in subsequent posts helping us retain the pure MVVM approach and not pollute the ViewModel with view-related concerns.