Bookmark and Share Share...    Subscribe to this feed Feed   About Christian Moser  


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>
 
 




Last modified: 2010-02-10 10:34:15
Copyright (c) by Christian Moser, 2011.

 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.
Jak
Commented on 5.September 2010
better if you provide a Sample of this Explnation.
Viral Dave
Commented on 8.September 2010
Great work...
Gopal
Commented on 16.October 2010
Why MainWindow knows about the view Model(have logical reference though property)
Donny Brasco
Commented on 15.November 2010
Great posts, wanted to see PRISM in the works and how would start my project using it,this clears up a lot of things. May you please provide source code so as to see it in code and study how this all ties up together
Donny Brasco
Commented on 15.November 2010
Great posts, wanted to see PRISM in the works and how would start my project using it,this clears up a lot of things. May you please provide source code so as to see it in code and study how this all ties up together
Sushil
Commented on 28.December 2010
Describe some thing more for new commers
Achim Koch
Commented on 11.February 2011
Thank you for your post. But, sorry, charts (modelling) and code doesent fit at all. There is no ShoppingCartService in your charts and there is no OrderService in your code. Can you please post some more consistent stuff? It's a little hard to put all pieces togehter, otherwise.
Achim Koch
Commented on 14.February 2011
I have coded it a little - not exactly the above modele but some of it.
But I don't know where to put the code. Can you help me out?
pouyan
Commented on 8.August 2011
these kinda articles ain't a tutorial. you have explained very short abour dependency injection and your code and diagrams are not useful at all. if you would uploaded a sample project for each article that would helped a lot.
nagarjunareddy
Commented on 9.August 2011
chala bagundhi....
alireza
Commented on 30.August 2011
thanks my dear!

Name
E-Mail (optional)
Comment