This project has moved and is read-only. For the latest updates, please go here.

Setting View.DataContext

Jan 11, 2012 at 9:40 AM

I do not understand the way the ViewModel constructor sets the view.DataContext:

if (SynchronizationContext.Current is DispatcherSynchronizationContext)
{
    Dispatcher.CurrentDispatcher.BeginInvoke(delegate {
         this.view.DataContext = this;
       }, new object[0]);
}
else
{
    view.DataContext = this;
}

Shouldn't the if and else branches be swapped?

Jan 14, 2012 at 9:17 PM
Edited Jan 14, 2012 at 9:18 PM

This is a good question. The short answer is that the code is correct in the ViewModel class and it shouldn’t be swapped.

// Constructor
protected ViewModel(IView view)
{
    this.view = view;

    // Check if the code is running within the WPF application model
    if (SynchronizationContext.Current is DispatcherSynchronizationContext)
    {
        // Set DataContext of the view has to be delayed so that the ViewModel can 
//
initialize the internal data (e.g. Commands) before the view starts with DataBinding. Dispatcher.CurrentDispatcher.BeginInvoke((Action)delegate() { this.view.DataContext = this; }); } else { // When the code runs outside of the WPF application model then we set the
// DataContext immediately.
view.DataContext = this; } }

Long answer:

The intention of the BeginInvoke code is to defer the setting of the DataContext with itself. This should happen after the constructor has been completed and the ViewModel is fully initialized.

However, this approach cannot be used when the code is not executed inside a WPF application. Then the else path sets the DataContext immediately. Examples when the Dispatcher is not used: