Bookmark and Share Share...    Subscribe to this feed Feed   About me...


A reference architecture for large WPF projects

Introduction

Choosing an adequate architecture is crucial for the success of a software project. You can have the best concepts, if your architecture does not perform, the user will have bad experiences while waiting for the application to load. Also aspects like it's robustness, maintainability or testability are important to address.

WPF provides a powerful databinding framework. If we could take advantage of this by using the MVVM pattern and decouple our views by dependency injection, we can build a powerful scaleable architecture.

These are the key components or patterns we want to use:

  • WPF DataBinding
  • Model-View-ViewModel pattern
  • Dependency Container (e.g. Unity)
  • Actions from the System.Windows.Interactivity library

How it works

The basic idea is to have a dependency container that builds up a view. The view has a viewmodel injected, that is bound to the DataContext. The viewmodel concentrates and provides data and commands for the view that it gets from services, that are injected by the constructor. The services live as singletons within the container.

Using this architecture allows you to build up loosely coupled views that interact magically together over common data coming from services in the background. It's very simple to rearrange or replace views, since they have to dependencies among each other.

Advantages of this architecture:

  • UI elements are easily replaced because of flexible databinding
  • The views are loosely coupled and quickly composed together
  • The viewmodel can be tested with conventional unit testing
  • Each service has a single purpose. They are easy to develop and make the architecture scalable.

Initializing the container and build up the main window

 
public class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<ICustomerService, CustomerService>();
        container.RegisterType<IShoppingCartService, ShoppingCartService>();
 
        MainWindow mainWindow = container.Resolve<MainWindow>();
        mainWindow.Show();
    }
}
 
 

Injecting the viewmodel to the view

By adding a [Dependency] attribute to the property, the dependency container resolves and injects the specified type after creating the view. The injected viewmodel is directly set to the data context of the view. The view itself contains no other logic.

 
public class MainWindow : Window
{
    [Dependency]
    public MainWindowViewModel ViewModel
    {
        set { DataContext = value; }
    }
 
    public MainWindow()
    {
        InitializeComponent();
    }
}
 
 

Implementing the viewmodel

 
public class MainWindowViewModel
{
    private ICustomerService _customerService;
 
    public MainWindowViewModel(ICustomerService customerService)
    {
        _customerService = customerService;
        Customers = new ListCollectionView(customerService.Customers);
    }
 
    public ICollectionView Customers { get; private set; }
}
 
 

Binding the data to the view

 
<Window x:Class="WpfTutorial.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ListBox ItemsSource="{Binding Customers}" />
</Window>
 
 



 Comments on this article

Show all comments
chinnappa
Commented on 13.January 2010
awesome !!
Alec
Commented on 26.January 2010
Great post. One thing I would change is rather than having a write-only ViewModel property, pass it as a parameter to the constructor of the window class.
WPF doesn't require parameterless constructors.
mukesh
Commented on 4.February 2010
thanks..
sagar tambe
Commented on 23.February 2010
This is think i m looking from long time. Architecture wise WPF make sense isn't it?
Jeremy
Commented on 18.March 2010
@Sagar

DI was around LONG before WPF. You should look at Martin Folwers articles from the beginning of this decade.
rashmin
Commented on 13.May 2010
great job...
Chris Bellew
Commented on 5.June 2010
Can this be done with MEF? Gotta love MEF.
Bill
Commented on 19.July 2010
Doesn't Prism wrap this functionality?
Manish K
Commented on 21.July 2010
Good Explanation
can we have source code to download?
StevenH77
Commented on 23.July 2010
Downloadable source would be great!
San
Commented on 28.July 2010
we can make good ny having code , from where we can have this souce code
San
Commented on 28.July 2010
we can make good practice having code , from where we can have this souce code
JIm
Commented on 11.August 2010
What a great idea, palagarize other peoples material, have ads and make money.. who says crime doesn't pay.

Name
E-Mail (optional)
Comment
About Christian Moser