Declaring your DataContext in markup

Declaring your DataContext in markup

  • Comments 2
  • Likes

This blog post was authored by Steve White, a Senior Content Developer on the Windows Phone team.

- Adam


Setting the DataContext property to a view model instance in your page markup can increase the “designability” of your pages in Visual Studio and Blend for Visual Studio. In this post I explain why, and demonstrate how it works.

So that a page’s UI elements can bind to a view model’s properties and commands, the view model is assigned to the page’s DataContext property. A common dev practice is to set the DataContext value for a page imperatively, using code-behind. Here’s an example from a sample app I created, called Bookstore.

C#
  1. public MainPage()
  2. {
  3.     InitializeComponent();
  4.  
  5.     this.DataContext = new BookstoreViewModel();
  6. }

The result is a sparse design UI, on both MainPage.xaml and in the Create Data Binding dialog.

image

I have databound TextBlocks and a databound ListBox in my page. I also have an item template, which is what I’m editing in the preceding screenshot. All this runs and looks great in the Windows Phone Emulator and on Windows Phone. But that constructor isn’t executed at design time, so my page is more challenging to style and to lay out.

Let’s see what happens if I comment out the DataContext assignment in my constructor and set the DataContext in markup instead. To do this, first open your XAML page. Then, in the Document Outline window, click PhoneApplicationPage; in the Properties window, click DataContext, and then click New. Click your view model type from the Select Object dialog box, and then click OK.

image

Here’s what my design surface in Visual Studio looks like now. Notice that the Path picker in the Create Data Binding dialog is now populated, based on the DataContext type and the properties that you can bind to.

image

The Create Data Binding dialog only needs a type to work from, but the bindings need the properties to be initialized with values. In my Bookstore app, I don’t want to reach out to my cloud service at design time so my initialization code checks to see whether the app is running in a design tool such as Visual Studio or Blend.

C#
  1. if (System.ComponentModel.DesignerProperties.IsInDesignTool)
  2.     // Load design-time books.
  3. else
  4.     // Load books from a cloud service.

You could use a view model locator if you need to pass parameters to your initialization code. A view model locator is a class that you can put into app resources. It has a property that exposes the view model, and your page’s DataContext binds to that property. Another pattern that the locator or the view model can use is dependency injection, which can construct a design-time or a run-time data provider (each of which implements a common interface), as applicable.

If for some reason none of these options work for you, you could try implementing a design-time data context. That’s a bigger topic than we can cover here, but one way of doing it is to use the Sample Data from Class feature in Blend, and which is demonstrated a little before the 12-minute mark in the video in the Inside Windows Phone – Data binding blog post.

I’ll leave you with one last tip. Did you notice that Visual Studio generated the XML namespace prefix local for the view model instance? If local is already being used elsewhere, Visual Studio generates a prefix based on the last segment of the CLR namespace. What I like to do is to use the exact CLR namespace, but replace periods with underscores. This way I never get collisions, even if I copy-and-paste code across pages.

2 Comments
You must be logged in to comment. Sign in or Join Now
  • Come on, show the Xaml code too.  ;)

  • I have a quite detailed write up of design time data, including the d:DataContext technique that you can use to set the context at design time even if you set the runtime DataContext in code behind. It is in MSDN Magazine, at msdn.microsoft.com/.../dn169081.aspx and is part of a series on MVVM.

    Laurent