d:DesignInstance in Blend 4

Let’s walk through an example of using d:DesignInstance for improving the design-time experience in Blend. For background, see my last post on the topic.

I’m going to be using the ContactManager sample from the Caliburn trunk. You can access the source of it here under: \trunk\samples\LOB Samples\Silverlight\ContactManager\

We’re only going to concern ourselves with one view/viewmodel pair:

  • ContactListView
  • ContactListPresenter

(This sample code still uses Caliburn’s old naming scheme that was influenced by the MVP pattern. “Presenter” here means “View Model” for all practical purposes.)

ContactListView displays a list of contacts in an ItemsControl on left side of the view. As you can see, there isn’t much visible in Blend.

The view opened in Blend 4. On the corresponding viewmodel, we have a property named Contacts that we’ll bind to the ItemsControl.

(Note that Caliburn is binding to this property using naming conventions, but we’ll need to add an explicit binding in order to play nice with Blend.)

Here’s what my ItemsControl looks like:

<ItemsControl x:Name="Contacts" 
              ItemsSource="{Binding Contacts}">
<!-- omitted for brevity -->
</ItemsControl>

Let’s select the ItemsControl in Blend and examine the data binding for the ItemsSource.

selecting the data binding editor for the ItemsSource

It’s a sad, empty little dialogue that greets us.

The depressingly empty Data Context tab.

Getting the Shape of Our Data Context

Let’s open up the XAML for ContactListView. In the root element, we’ll set the design-time data context using the d:DesignInstance markup extension. It looks like this:

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:Controls="clr-namespace:Caliburn.Silverlight.ApplicationFramework.Controls;assembly=Caliburn.Silverlight.ApplicationFramework"
             xmlns:rm="clr-namespace:Caliburn.PresentationFramework.RoutedMessaging;assembly=Caliburn.PresentationFramework"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d" x:Class="ContactManager.Views.ContactListView"
             xmlns:local="clr-namespace:ContactManager.Presenters"             
             Height="400"
             Width="750"
             d:DataContext="{d:DesignInstance local:ContactListPresenter}"
             rm:Message.Attach="[Event Loaded] = [Action LoadContacts]">

<!-- omitted for brevity -->
</UserControl>

Wow, that’s a lot of namespaces. We’re only concerned with two lines though. The first one is

    xmlns:local="clr-namespace:ContactManager.Presenters" 

This also use to reference our local type in XAML.

The second is

    d:DataContext="{d:DesignInstance local:ContactListPresenter}" 

This tells Blend that we want to use the ContactListPresenter for our design-time data context. However, this doesn’t create an instance of the type and we won’t see any data appear in Blend. Instead, this tells Blend what the “shape” of our data context is. In other words, Blend uses reflection to learn about the properties so that it can show us a lot more in the data binding editor.

Let’s open that up again.

a really useful data binding engine

Much less depressing. This also means that when I drill down and edit the ItemTemplate, Blend is aware of the data context and I get support for bindings there as well. Booya.

Getting Some Sample Data

I said earlier that d:DesignInstance does not create an instance of the specified type. You can make it create an instance though by setting the IsDesignTimeCreatable property to true. Now, we don’t want to do this with ContactListPresenter because it has a couple of dependencies injected into it’s constructor. So in order to provide a little sample data for the designer, I’ve created a new class to use as my design-time viewmodel:

public class SampleContactListPresenter
{
    public List<Contact> Contacts {get;set;}    
    
    public SampleContactListPresenter()
    {
        Contacts = new List<Contact>
        {
            new Contact{ FirstName="Ford", LastName="Prefect"},
            new Contact{ FirstName="Author", LastName="Dent"},
        };
    }
    
}

I could have derived this from ContactListPresenter, but that would have been a lot of unnecessary work. A better choice would be for my design-time viewmodel and my real viewmodel to implement a common interface. That would help them maintain the same shape. (An even better choice would be to use d:DesignData, but that’s another post).

In this case, I decided to keep it really simple.

After adding this class, I need to change the line in my XAML that creates the design-time data context to this:

d:DataContext="{d:DesignInstance local:SampleContactListPresenter, IsDesignTimeCreatable=True}"

and now I can see some sample data in Blend:

Some actual, real not-so real or actual data.

 

N.B. I discovered after I worked through this that the ContactListPresenter in the trunk doesn’t get along well with d:DesignInstance. I haven’t isolated the exact problem yet, but you’ll  need to modify the class if you want to follow along with this tutorial. Change the class so that it is only inheriting from ScreenConductor<IContactDetailsPresenter>:

public class ContactListPresenter : ScreenConductor<IContactDetailsPresenter>, IContactListPresenter

Posted 03-29-2010 4:12 PM by Christopher Bennage

[Advertisement]

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)