WPF & Silverlight Designer

The Visual Designer for creating WPF & Silverlight applications in Visual Studio

Sample Data in the WPF and Silverlight Designer

Sample Data in the WPF and Silverlight Designer

Rate This
  • Comments 3

Objective

Requirements

Retail release of Visual Studio 2010 and the latest Silverlight 4 tools for Visual Studio 2010.

Background 

Cider and Blend 4

Developers using a visual Designer use sample data to light up their UI at design-time; to cause the Designer to render like it will at run-time. This time saving feature is especially important when designing DataTemplates or adjusting the layout of a DataGrid since the developer will not have to actually run the application to see what it will render like with data.

Sample data in Cider and Blend is easy to understand and wire up.

Sample data files are XAML files. Each sample data file contains one or more instances of user type's instantiated in XAML. The XAML sample data file and resulting instances of data are connected to the UI using the d:DesignData MarkupExtension. d:DesignData can be applied to a data source declared in XAML like a CollectionViewSource, DomainDataSource or can be assigned to a d:DataContext property.

Each sample data file has an associated Build Action that determines if d:DesignData will create actual instances of the types in the sample data file or if faux types will be created. Faux types are necessary when the types in the sample data file are not creatable or if read-only properties need to be populated with sample data values.

Blend 4

Blend has tooling to create and modify XAML sample data for a class. Blend also provides a sample data drag and drop experience to wire up the d:DataContext and appropriate properties.

Blend provides an additional feature that enables creating XML sample data on the fly without a predefined class. The XML sample data can then be easily be configured and modified. This XML sample data only works in Blend.

To learn more about Blend please see the Expression Blend Blog, Unni's Blog, Kirupa's Blog or Christian Schormann's Blog.

Faux Types and Real Types 

The term faux type is used in this document to indicate that a cloned type will be created instead of your actual type. Benefits of faux types include the ability to create an otherwise non-creatable type in sample data, the ability to set read-only properties in sample data and the by-passing of code in the real type's constructor.

When using real types in sample data, be aware that any code in the type's constructor will be executed at design-time. For an entity object this would not normally be an issue, but if the real type is a ViewModel, the code in that ViewModel's constructor will be executed. If that constructor's code loads data from a database for example, problems could occur in the Designer when the sample data is loaded. User code running at design-time is responsible for over 20% of all Designer load failures. You can read up on running code in a constructor in this blog post.

Images in Sample Data Files 

WPF Sample Data Files Only

If the image is part of the project, it can be referenced using the below relative folder syntax.

<m:Customer FirstName="Alfons" LastName="Parovszky" Photo="../Images/image01.png">

WPF and Silverlight Sample Data Files

All images in Silverlight sample data files require the pack syntax. WPF projects must use this syntax if the image is located in another assembly:

<m:Customer FirstName="Alfons" LastName="Parovszky" 
            Photo="/SLSampleDataScenarios;component/Images/image01.png">

If the image is not part of any project, you can use the below file:/// URI syntax to use an image in a sample data file.

<m:Customer FirstName="Alfons" LastName="Parovszky" 
            Photo="file:///c:/Images/markbou.jpg">

Adding New Sample Data File 

The following applies to both WPF and Silverlight applications.

  • Add a new ResourceDictionary or Text File to the project.
    • If ResourceDictionary delete the default file content.
    • If Text File, change file extension to .xaml
  • Using the file properties, set build action to either:
    • DesignData – will create faux types
    • DesignDataWithDesignTimeCreatableTypes – will create actual types
  • Using the file properties, set Copy to Output Directory to: Do not copy
  • Using the file properties, set Custom Tool:  <blank>
  • Using XAML Editor add your sample data content to the file.

Sample Data File Properties

Single Instance Sample Data Example

<m:Customer 
    xmlns:m="clr-namespace:SampleDataScenarios.Model" 
    FirstName="Alfons" LastName="Parovszky" 
    Photo="../Images/image01.png">
</m:Customer>

Multiple Instance Sample Data Example

<m:Customers xmlns:m="clr-namespace:SampleDataScenarios.Model">
    <m:Customer FirstName="Alfons" LastName="Parovszky" Photo="../Images/image01.png">
        <m:Customer.Addresses>
            <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
    <m:Customer FirstName="Lori" LastName="Penor" Photo="../Images/image02.png">
        <m:Customer.Addresses>
            <m:Address LineOne="126 East St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3001 2st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
    <m:Customer FirstName="Justin" LastName="Harrison" Photo="../Images/image03.png">
        <m:Customer.Addresses>
            <m:Address LineOne="127 West St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3002 3st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
</m:Customers>

WPF Supported Sample Data File Scenarios

For sample data files where the root object is a single instance, simply add the type to the sample data file as done in Single Instance Sample Data Example above.

For collections, the root object can be an ArrayList or a custom type that derives from a collection or generic collection as done in Multiple Instance Sample Data Example above. Notice that WPF can also use the same technique as outlined below in Silverlight Scenarios. The Multiple Instance Sample Data Example uses the below DesignSampleDataCollection class as the root instead of an ArrayList.

Silverlight Supported Sample Data File Scenarios

For sample data files where the root object is a single instance, simply add the type to the sample data file as done in Single Instance Sample Data Example above.

For collections, the root object must be a type that derives from a collection or generic collection.

Non-WCF RIA Services Scenario

If the project does not have a collection object for the desired root type and the type does not derive from the RIA Services Entity object, you need to create a generic reusable collection like the below DesignSampleDataCollection.

C#

namespace SampleDataScenarios.Model {
  public class DesignTimeSampleDataCollection : List<Object> {

    public DesignTimeSampleDataCollection() { }
  }
}

VB.NET

Public Class DesignTimeSampleDataCollection
  Inherits List(Of Object)

  Public Sub New()

  End Sub

End Class

WCF RIA Services Scenario

If the project does not have a collection object for the desired root type and the type derives from the RIA Services Entity object, you need to create a generic reusable collection like the below DesignRIAEntitySampleDataCollection.

namespace ContosoSales.SampleData {
    public class DesignRIAEntitySampleDataCollection : 
          List<System.ServiceModel.DomainServices.Client.Entity> {

        public DesignRIAEntitySampleDataCollection() { }
    }
}

Consuming Sample Data File 

The d:DesignData Markup Extension assumes the role of a sample data file loader and parser that provides instantiated or faux types to the consumer.

Sample Data Consumers

The following design-time properties can consume the sample data provided by d:DesignData:

  • d:DataContext can be set on any FrameworkElement
  • d:DesignSource can be set on a CollectionViewSource
  • d:DesignData can be set on a DomainDataContext (RIA Services data object)

WPF Sample Data Scenarios 

Open either solution: CS-SampleDataScenarios or VB-SampleDataScenarios.

Rebuild solution.

The WPF samples are in the SampleDataScenarios project.

Demo-01 Single Customer

Open Demo01SingleCustomer.xaml.

This is an example of a single instance sample data file consumed by a form. The single instance of Customer has 2 instances of Address.

<m:Customer 
    xmlns:m="clr-namespace:SampleDataScenarios.Model" 
    FirstName="Alfons" LastName="Parovszky" 
    Photo="../Images/image01.png">
    <m:Customer.Addresses>
        <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
        <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
    </m:Customer.Addresses>
</m:Customer>

In the below form, the Customer type is available in the root Grid's DataContext. This is important because the presence of d:DesignData and sample data not only feeds the DataContext to render data, but also enables the Designer tooling for creating and editing bindings using the Binding Builder.

Connecting Sample Data

In the below XAML the CustomerSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DataContext for the Grid. Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled.

<Grid d:DataContext="{d:DesignData Source=/SampleData/CustomerSampleData.xaml}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Text="Demo-01 Single Customer" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" Margin="11" />

    <Grid Grid.Row="1" Margin="6">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
        <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

        <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
        <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

        <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
        <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

        <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

        <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="75" />
                            <ColumnDefinition Width="30" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Path=LineOne}" />
                        <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
                        <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
                        <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>

    <Image VerticalAlignment="Top" Source="{Binding Path=Photo}" Grid.Row="1" Grid.Column="1" Margin="6" />
</Grid>

Demo-02 Single Not Creatable Customer

Open Demo02SingleNotCreatableCustomer.xaml and NotCreatableCustomer.cs.

This is an example of a single instance sample data file where the entity object is not creatable. The NotCreatableCustomer class has a private constructor. The single instance of NotCreatableCustomer has 2 instances of Address.

Non-creatable types are common scenario in .NET, making this feature a very important addition to the Designer tooling. For example, RIA Services Entity types or types that are created by factories cannot be instantiated. Without this feature sample data would not work and the Designer tooling would be unable to provide DataContext and property name lists for a type.

Important

Sample data files that contain non-creatable types must have their Build Action set to: DesignData and not DesignDataWithDesignTimeCreatableTypes.


<m:Customer 
    xmlns:m="clr-namespace:SampleDataScenarios.Model" 
    FirstName="Alfons" LastName="Parovszky" 
    Photo="../Images/image01.png" Ranking="101">
    <m:Customer.Addresses>
        <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
        <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
    </m:Customer.Addresses>
</m:Customer>

In the below form, the NotCreatableCustomer type is available in the root Grid's DataContext. Again, even though the NotCreatableCustomer type has a private constructor the sample data displays and the Binding Builder works normally.

Connecting Sample Data

In the below XAML the NotCreatableCustomerSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DataContext for the Grid. Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled.

<Grid d:DataContext="{d:DesignData Source=/SampleData/NotCreatableCustomerSampleData.xaml}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
        
    <TextBlock Text="Demo-02 Single Not Creatable Customer" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" Margin="11" />
        
    <Grid Grid.Row="1" Margin="6">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
        <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

        <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
        <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

        <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
        <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

        <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

        <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="75" />
                            <ColumnDefinition Width="30" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Path=LineOne}" />
                        <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
                        <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
                        <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>
        
    <Image VerticalAlignment="Top" Source="{Binding Path=Photo}" Grid.Row="1" Grid.Column="1" Margin="3" />
</Grid>

Demo-03 Customer ViewModel

Open Demo03CustomerViewModel.xaml.

This is an example of using a design-time ViewModel as the d:DataContext. DesignTimeCustomerViewModel derives from CustomerViewModel. In its constructor it populates the ViewModel properties and collection. Since the DesignTimeCustomerViewModel's properties are populated, they are rendered on the design surface.

The below code demonstrates creating sample data instead of using the typical sample data XAML file.

C#

namespace SampleDataScenarios.ViewModel {
  public class DesignTimeCustomerViewModel : CustomerViewModel {

    public DesignTimeCustomerViewModel()
      : base() {

      base.Customer = new Customer() {
        FirstName = "Alfons", LastName = "Parovszky", Photo = "../Images/image01.png"
      };
      base.Customer.CalculateRank();
      base.Customer.Addresses.Add(
          new Address() { LineOne = "125 North St", City = "Greatville", State = "CA", Zip = "98004" });
      base.Customer.Addresses.Add(
          new Address() { LineOne = "3000 1st St NE", City = "Coolville", State = "CA", Zip = "98004" });
    }
  }
}

VB.NET

Public Class DesignTimeCustomerViewModel
  Inherits CustomerViewModel

  Public Sub New()
    MyBase.New()

    MyBase.Customer = New Customer With {.FirstName = "Alfons", .LastName = "Parovszky", .Photo = "../Images/image01.png"}
    MyBase.Customer.CalculateRank()
    MyBase.Customer.Addresses.Add(New Address With {.LineOne = "125 North St", .City = "Greatville", .State = "CA", .Zip = "98004"})
    MyBase.Customer.Addresses.Add(New Address With {.LineOne = "3000 1st St NE", .City = "Coolville", .State = "CA", .Zip = "98004"})

  End Sub

End Class

Connecting Sample Data

The below XAML demonstrates using d:DesignInstance with IsDesignTimeCreatable set to true to have Visual Studio instantiate DesignTimeCustomerViewModel and assign the instance as the d:DataContext. Since the instantiated instance has properties populated with data, that data will render exactly like other XAML file sample data in the Designer. This works because the DesignTimeCustomerViewModel is creatable at design-time and the below DesignInstance has IsDesignTimeCreatable set to true. Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled.

<Grid d:DataContext="{d:DesignInstance vm:DesignTimeCustomerViewModel, IsDesignTimeCreatable=True}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Text="{Binding Path=FormTitle}" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" Margin="11" />

    <Grid Grid.Row="1" Margin="6" DataContext="{Binding Path=Customer}">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
        <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

        <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
        <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

        <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
        <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

        <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

        <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="100" />
                            <ColumnDefinition Width="75" />
                            <ColumnDefinition Width="30" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="{Binding Path=LineOne}" />
                        <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
                        <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
                        <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

    </Grid>

    <Image VerticalAlignment="Top" Source="{Binding Path=Customer.Photo}" Grid.Row="1" Grid.Column="1" Margin="6" />
</Grid>


Demo-04 Northwind Master Details Details

Open Demo04NorthwindMasterDetailsDetails.xaml.

This is an example of using chained CollectionViewSources where the top level CollectionViewSource is the DataContext for a form. It is assumed that the CollectionViewSources will be populated at run-time from a code-behind method.

This example uses an EntityFramework model for the entity types.

The below sample data file has 2 instances of Customer each with 1 instance of Order and each Order has three instances of Order_Detail.

<sysCol:ArrayList xmlns:sysCol="clr-namespace:System.Collections;assembly=mscorlib"
                  xmlns:nw="clr-namespace:SampleDataScenarios.NorthwindModel">
    <nw:Customer Contact_Name="Jim Hance" Company_Name="Adatum" Contact_Title="Software Developer" Customer_ID="1">
        <nw:Customer.Orders>
            <nw:Order Order_Date="12/12/2009" Ship_Name="Jim Hance" Customer_ID="1" Order_ID="1"
                      Ship_Address="125 North St" Employee_ID="74">
                <nw:Order.Order_Details>
                    <nw:Order_Detail Product_ID="125" Discount="50" Order_ID="1" Quantity="5" 
                                     Unit_Price="75.99" />
                    <nw:Order_Detail Product_ID="742" Order_ID="1" Quantity="9" Unit_Price="5.99" />
                    <nw:Order_Detail Product_ID="2555" Order_ID="1" Quantity="50" Unit_Price="6.25" />
                </nw:Order.Order_Details>
            </nw:Order>
        </nw:Customer.Orders>
    </nw:Customer>
    <nw:Customer Contact_Name="Michael Patten" Company_Name="Contoso" Contact_Title="Sales Manager" Customer_ID="2">
        <nw:Customer.Orders>
            <nw:Order Order_Date="12/12/2009" Ship_Name="Michael Patten" Customer_ID="2" Order_ID="71"
                      Ship_Address="125 North St" Employee_ID="55">
                <nw:Order.Order_Details>
                    <nw:Order_Detail Product_ID="547" Discount="50" Order_ID="71" Quantity="5" 
                                     Unit_Price="75.99" />
                    <nw:Order_Detail Product_ID="62" Order_ID="71" Quantity="9" Unit_Price="5.99" />
                    <nw:Order_Detail Product_ID="11" Order_ID="71" Quantity="50" Unit_Price="6.25" />
                </nw:Order.Order_Details>
            </nw:Order>
        </nw:Customer.Orders>
    </nw:Customer>
</sysCol:ArrayList>

Connecting Sample Data

In the below XAML the NorthwindSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DesignSource for the top level customersViewSource CollectionViewSource. The two remaining CollectionViewSources chain to collection properties on the customersViewSource.

Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled. Notice the two DataGrid ItemsSource's are the two chained CollectionViewSources. The two DataGrid's also have their sample data populated and the Designer Binding Builder tooling is enabled.

<UserControl.Resources>
  <CollectionViewSource 
    x:Key="customersViewSource" 
    d:DesignSource="{d:DesignData Source=../SampleData/NorthwindSampleData.xaml}" />
  <CollectionViewSource 
    x:Key="customersOrdersViewSource" 
    Source="{Binding Path=Orders, Source={StaticResource customersViewSource}}" />
  <CollectionViewSource 
    x:Key="customersOrdersOrder_DetailsViewSource" 
    Source="{Binding Path=Order_Details, Source={StaticResource customersOrdersViewSource}}" />
</UserControl.Resources>
<Grid DataContext="{StaticResource customersViewSource}">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="200" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <TextBlock Text="Demo-04 Northwind Master Details Details" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" Margin="11" />

  <ListView 
    SelectedIndex="0" ItemsSource="{Binding}" Name="customersListView" SelectionMode="Single" 
    Margin="3.5,4" Grid.RowSpan="2" Grid.Row="1">
    <ListView.ItemContainerStyle>
      <Style>
        <Setter Property="Control.HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="Control.VerticalContentAlignment" Value="Stretch" />
      </Style>
    </ListView.ItemContainerStyle>
    <ListView.View>
      <GridView>
        <GridViewColumn x:Name="company_NameColumn" Header="Company Name" Width="90">
          <GridViewColumn.CellTemplate>
            <DataTemplate>
              <TextBox 
                Margin="-6,-1" 
                Text="{Binding Path=Company_Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
            </DataTemplate>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn x:Name="contact_NameColumn" Header="Contact Name" Width="90">
          <GridViewColumn.CellTemplate>
            <DataTemplate>
              <TextBox 
                Margin="-6,-1" 
                Text="{Binding Path=Contact_Name, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
            </DataTemplate>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
      </GridView>
    </ListView.View>
  </ListView>

  <Grid Grid.Column="1" Margin="3.5" Grid.Row="1">
    <DataGrid 
      AutoGenerateColumns="False" EnableRowVirtualization="True" 
      ItemsSource="{Binding Source={StaticResource customersOrdersViewSource}}" 
      Name="ordersDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Margin="3.5">
      <DataGrid.Columns>
        <DataGridTextColumn 
          x:Name="order_IDColumn" Binding="{Binding Path=Order_ID}" Header="Order ID" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="customer_IDColumn" Binding="{Binding Path=Customer_ID}" 
          Header="Customer ID" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="employee_IDColumn" Binding="{Binding Path=Employee_ID}" 
          Header="Employee ID" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_NameColumn" Binding="{Binding Path=Ship_Name}" 
          Header="Ship Name" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_AddressColumn" Binding="{Binding Path=Ship_Address}" 
          Header="Ship Address" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_CityColumn" Binding="{Binding Path=Ship_City}" 
          Header="Ship City" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_RegionColumn" Binding="{Binding Path=Ship_Region}" 
          Header="Ship Region" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_Postal_CodeColumn" Binding="{Binding Path=Ship_Postal_Code}" 
          Header="Ship Postal Code" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_CountryColumn" Binding="{Binding Path=Ship_Country}" 
          Header="Ship Country" Width="SizeToHeader" />
        <DataGridTextColumn 
          x:Name="ship_ViaColumn" Binding="{Binding Path=Ship_Via}" 
          Header="Ship Via" Width="SizeToHeader" />
        <DataGridTemplateColumn 
          x:Name="order_DateColumn" Header="Order Date" Width="SizeToHeader">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <DatePicker 
                SelectedDate="{Binding Path=Order_Date, Mode=TwoWay, 
                                ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn x:Name="required_DateColumn" Header="Required Date" Width="SizeToHeader">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <DatePicker 
                SelectedDate="{Binding Path=Required_Date, Mode=TwoWay, 
                                ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn x:Name="shipped_DateColumn" Header="Shipped Date" Width="SizeToHeader">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <DatePicker 
                SelectedDate="{Binding Path=Shipped_Date, Mode=TwoWay, 
                                ValidatesOnExceptions=true, NotifyOnValidationError=true}" />
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn 
          x:Name="freightColumn" Binding="{Binding Path=Freight}" 
          Header="Freight" Width="SizeToHeader" />
      </DataGrid.Columns>
    </DataGrid>
  </Grid>
  <DataGrid 
    AutoGenerateColumns="False" EnableRowVirtualization="True" Grid.Column="1" Grid.Row="2" 
    ItemsSource="{Binding Source={StaticResource customersOrdersOrder_DetailsViewSource}}" 
    Name="order_DetailsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Margin="3.5">
    <DataGrid.Columns>
      <DataGridTextColumn 
        x:Name="order_IDColumn1" Binding="{Binding Path=Order_ID}" 
        Header="Order ID" Width="SizeToHeader" />
      <DataGridTextColumn 
        x:Name="product_IDColumn" Binding="{Binding Path=Product_ID}" 
        Header="Product ID" Width="SizeToHeader" />
      <DataGridTextColumn 
        x:Name="unit_PriceColumn" Binding="{Binding Path=Unit_Price}" 
        Header="Unit Price" Width="SizeToHeader" />
      <DataGridTextColumn 
        x:Name="quantityColumn" Binding="{Binding Path=Quantity}" 
        Header="Quantity" Width="SizeToHeader" />
      <DataGridTextColumn 
        x:Name="discountColumn" Binding="{Binding Path=Discount}" 
        Header="Discount" Width="SizeToHeader" />
    </DataGrid.Columns>
  </DataGrid>
</Grid>

Demo-05 Select Customer From List

Open Demo05SelectCustomerFromList.xaml.

This is an example of a multiple instance sample data file consumed by a form. The sample data consists of 3 Customers, each with 2 Addresses.

<m:Customers xmlns:m="clr-namespace:SampleDataScenarios.Model">
    <m:Customer FirstName="Alfons" LastName="Parovszky" Photo="../Images/image01.png">
        <m:Customer.Addresses>
            <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
    <m:Customer FirstName="Lori" LastName="Penor" Photo="../Images/image02.png">
        <m:Customer.Addresses>
            <m:Address LineOne="126 East St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3001 2st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
    <m:Customer FirstName="Justin" LastName="Harrison" Photo="../Images/image03.png">
        <m:Customer.Addresses>
            <m:Address LineOne="127 West St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3002 3st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
</m:Customers>

In the below form, the collection of Customers is available in the root Grid's DataContext. This is important because the presence of d:DesignData and sample data not only feeds the DataContext to render data, but also enables the Designer tooling for creating and editing bindings in the Binding Builder.

The data entry form to the right of the ListBox, has its DataContext set to the ListBox.SelectedItem. When ListBox selection changes the form data automatically changes.

Connecting Sample Data

In the below XAML the CustomersSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DataContext for the Grid. Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled.

<Grid d:DataContext="{d:DesignData Source=/SampleData/CustomersSampleData.xaml}">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="126" />
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <TextBlock Text="Demo-05 Select Customer From List" Grid.ColumnSpan="3" 
                  FontWeight="Bold" FontSize="14" Margin="11" />

  <ListBox SelectedIndex="0" x:Name="lbCustomers" Grid.Row="1" Margin="6" ItemsSource="{Binding}">
    <ListBox.ItemTemplate>
      <DataTemplate>
        <StackPanel Orientation="Horizontal">
          <TextBlock Text="{Binding Path=FirstName}" Margin="0,0,4,0" />
          <TextBlock Text="{Binding Path=LastName}" />
        </StackPanel>
      </DataTemplate>
    </ListBox.ItemTemplate>
  </ListBox>

  <Grid Grid.Row="1" Margin="6" Grid.Column="1" DataContext="{Binding ElementName=lbCustomers, Path=SelectedItem}">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
    <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

    <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
    <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

    <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
    <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

    <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

    <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="100" />
              <ColumnDefinition Width="75" />
              <ColumnDefinition Width="30" />
              <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Path=LineOne}" />
            <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
            <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
            <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
          </Grid>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>

  </Grid>

  <Image VerticalAlignment="Top" Source="{Binding Path=Photo}" Grid.Row="1" Grid.Column="2" Margin="6" />
</Grid>


Demo-06 Typed DataTemplate

Open Demo06TypedDataTemplate.xaml.

The example demonstrates the requirements for displaying sample data when that data is rendered using a typed DataTemplate in a Resource. The key point here is that the DataTemplate is typed and in a Resource.

<m:Customer 
    xmlns:m="clr-namespace:SampleDataScenarios.Model" 
    FirstName="Alfons" LastName="Parovszky" 
    Photo="../Images/image01.png">
    <m:Customer.Addresses>
        <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
        <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
    </m:Customer.Addresses>
</m:Customer>

Typed DataTemplates are looked up based on DataType. If WPF cannot match the DataTemplate.DataType property with the sample data type, the DataTemplate will not be used to render the sample data. Additionally, any mismatch will also affect using the Designer Binding Builder as it won't be able to resolve properties in the DataContext. The results of a mismatch are pictured in the right column of the two below tables.

When the sample data file Build Action is DesignDataWithDesignTimeCreatableTypes, the DataTemplate must have the d:IsDesignTimeCreatable property set to True or not set at all.

Correct Setting on Data Template When
Build Action = DesignDataWithDesignTimeCreatableTypes

Incorrect Setting on the DataTemplate When
Build Action = DesignDataWithDesignTimeCreatableTypes


Notice that ListBox is not using the typed DataTemplate to render the Address items.

<DataTemplate DataType="{x:Type m:Address}"

d:IsDesignTimeCreatable="True" >

---or---

<DataTemplate DataType="{x:Type m:Address}">

<DataTemplate DataType="{x:Type m:Address}"

d:IsDesignTimeCreatable="False" >

When the sample data file Build Action is DesignData, the DataTemplate must have the d:IsDesignTimeCreatable property set to False.

Correct Setting on the DataTemplate
Build Action = DesignData

Incorrect Setting on the DataTemplate
Build Action = DesignData


Notice that ListBox is not using the typed DataTemplate to render the Address items.

<DataTemplate DataType="{x:Type m:Address}"

d:IsDesignTimeCreatable="False" >

<DataTemplate DataType="{x:Type m:Address}"

d:IsDesignTimeCreatable="True" >

---or---

<DataTemplate DataType="{x:Type m:Address}">


Connecting Sample Data

In the below XAML the CustomerSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DataContext for the Grid. Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled.

<UserControl.Resources>
  <!--Because the sample data is using the DesignDataWithDesignTimeCreatableTypes build action, the 
      DataTemplate must have the property d:IsDesignTimeCreatable="True" or not at all so that the  
      types will match and be resolved correctly by the designer.-->
  <DataTemplate DataType="{x:Type m:Address}" d:IsDesignTimeCreatable="True" >
    <Grid>
      <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="75" />
        <ColumnDefinition Width="30" />
        <ColumnDefinition Width="Auto" />
      </Grid.ColumnDefinitions>
      <TextBlock Text="{Binding Path=LineOne}" />
      <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
      <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
      <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
    </Grid>
  </DataTemplate>

</UserControl.Resources>
<Grid d:DataContext="{d:DesignData Source=/SampleData/CustomerSampleData.xaml}">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <TextBlock Text="Demo-06 Typed DataTemplate" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" Margin="11" />

  <Grid Grid.Row="1" Margin="6">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
    <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

    <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
    <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

    <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
    <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

    <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

    <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2" />

  </Grid>

  <Image VerticalAlignment="Top" Source="{Binding Path=Photo}" Grid.Row="1" Grid.Column="1" Margin="6" />
</Grid>

Silverlight Sample Data Scenarios 

The above WPF scenarios are also valid for Silverlight and won't be repeated here. The biggest difference between the two platforms with respect to sample data is the required pack syntax for images in sample data files.

Open either solution: CS-SampleDataScenarios or VB-SampleDataScenarios.

Rebuild solution.

The WPF samples are in the SLSampleDataScenarios project.

Demo-01 Single Customer

Open Demo01SingleCustomer.xaml.

This is an example of a single instance sample data file consumed by a form. The single instance of Customer has 2 instances of Address. Notice the assembly name; component syntax is used to identify an image in the project that has its Build Action set to Resource.

<m:Customer 
    xmlns:m="clr-namespace:SLSampleDataScenarios.Model" 
    FirstName="Alfons" LastName="Parovszky" 
    Photo="/SLSampleDataScenarios;component/Images/image01.png">
    <m:Customer.Addresses>
        <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
        <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
    </m:Customer.Addresses>
</m:Customer>

In the below form, the Customer type is available in the root Grid's DataContext. This is important because the presence of d:DesignData and sample data not only feeds the DataContext to render data, but also enables the Designer tooling for creating and editing bindings in the Binding Builder.

Connecting Sample Data

In the below XAML the CustomerSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DataContext for the Grid. Child controls of the Grid can data bind to properties on the DataContext and the Designer Binding Builder tooling is enabled.

<Grid d:DataContext="{d:DesignData Source=../SampleData/CustomerSampleData.xaml}">
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <TextBlock Text="Demo-01 Single Customer" Grid.ColumnSpan="2" FontWeight="Bold" FontSize="14" Margin="11" />

  <Grid Grid.Row="1" Margin="6">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
    <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

    <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
    <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

    <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
    <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

    <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

    <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="100" />
              <ColumnDefinition Width="75" />
              <ColumnDefinition Width="30" />
              <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Path=LineOne}" />
            <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
            <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
            <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
          </Grid>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>

  </Grid>

  <Image VerticalAlignment="Top" Source="{Binding Path=Photo}" Grid.Row="1" Grid.Column="1" Margin="6" />
</Grid>


Demo-02 Customers DataSources Window

Open Demo02CustomersDataSourcesWindow.xaml.

This is an example of using a CollectionViewSource that has sample data as the DataContext for a form. It is assumed that the CollectionViewSource will be populated at run-time from a code-behind method.

The below sample data file has 3 instances of Customer, each with 2 instances of Address. Notice the root collection.

<m:Customers xmlns:m="clr-namespace:SLSampleDataScenarios.Model">
<m:Customer FirstName="Alfons" LastName="Parovszky" 
            Photo="/SLSampleDataScenarios;component/Images/image01.png">
        <m:Customer.Addresses>
            <m:Address LineOne="125 North St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3000 1st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
    <m:Customer FirstName="Lori" LastName="Penor" 
                Photo="/SLSampleDataScenarios;component/Images/image02.png">
        <m:Customer.Addresses>
            <m:Address LineOne="126 East St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3001 2st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
    <m:Customer FirstName="Justin" LastName="Harrison" 
                Photo="/SLSampleDataScenarios;component/Images/image03.png">
        <m:Customer.Addresses>
            <m:Address LineOne="127 West St" City="Greatville" State="CA" Zip="98004" />
            <m:Address LineOne="3002 3st St NE" City="Coolville" State="CA" Zip="98004" />
        </m:Customer.Addresses>
    </m:Customer>
</m:Customers>

In the below form, the ComboBox is used to set the CurrentItem for the CollectionViewSource. The Grid that contains the Customer data entry form has its DataContext set to the CollectionViewSource. When the ComboBox selection changes the CollectionViewSource CurrentItem, the data entry form CurrentItem will automatically change. This is one technique for providing record selection.

Connecting Sample Data

In the below XAML, the CustomersSampleData.xaml file is loaded and parsed by the d:DesignData Markup Extension and assigned to the d:DesignSource for the CollectionViewSource.

<UserControl.Resources>
  <CollectionViewSource 
    x:Key="customerViewSource" 
    d:DesignSource="{d:DesignData Source=../SampleData/CustomersSampleData.xaml}" />
</UserControl.Resources>
<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>

  <TextBlock 
    Text="Demo-02 Customers Data Sources Window" FontWeight="Bold" 
    FontSize="14" Margin="11" />

  <StackPanel 
    Margin="6" Orientation="Horizontal" Grid.Row="1" 
    DataContext="{StaticResource customerViewSource}">
    <TextBlock VerticalAlignment="Center" Text="Select Customer:" Margin="7,0"  />
    <ComboBox Width="200" VerticalAlignment="Center" ItemsSource="{Binding}">
      <ComboBox.ItemTemplate>
        <DataTemplate>
          <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=FirstName}" Margin="0,0,7,0" />
            <TextBlock Text="{Binding Path=LastName}" />
          </StackPanel>
        </DataTemplate>
      </ComboBox.ItemTemplate>
    </ComboBox>
  </StackPanel>

  <Grid Grid.Row="2" Margin="6" DataContext="{StaticResource customerViewSource}">
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="Auto" />
      <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Text="First Name:" VerticalAlignment="Center" Width="75" />
    <TextBox Text="{Binding Path=FirstName}" VerticalAlignment="Center" Grid.Column="1"/>

    <TextBlock Text="Last Name:" VerticalAlignment="Center" Width="75" Grid.Row="1" />
    <TextBox Text="{Binding Path=LastName}" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />

    <TextBlock Text="Ranking:" VerticalAlignment="Center" Width="75" Grid.Row="2" />
    <TextBlock Text="{Binding Path=Ranking}" VerticalAlignment="Center"  Grid.Row="2" Grid.Column="1" />

    <TextBlock Margin="7" Text="Addresses" FontWeight="Bold" Grid.Row="3" Grid.ColumnSpan="2" />

    <ListBox ItemsSource="{Binding Path=Addresses}" Grid.Row="4" Grid.ColumnSpan="2">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="100" />
              <ColumnDefinition Width="75" />
              <ColumnDefinition Width="30" />
              <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Path=LineOne}" />
            <TextBlock Text="{Binding Path=City}" Grid.Column="1" />
            <TextBlock Text="{Binding Path=State}" Grid.Column="2" />
            <TextBlock Text="{Binding Path=Zip}" Grid.Column="3" />
          </Grid>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>

    <Image VerticalAlignment="Top" Source="{Binding Path=Photo}" Grid.RowSpan="5" Grid.Column="2" Margin="6" />
  </Grid>
    
</Grid>

WCF RIA Services Sample Data Scenario 

The below scenario will concentrate on surfacing design-time sample data in the Designer.

Open solution: ContosoSales.Mix10.

Rebuild solution.

Open \Views\Home.xaml.

This is an example form from the PDC 2010 RIA Services Demo. This demo has been upgraded to display design-time sample data.

The sample data file contains 2 Store records that each contains 2 Contacts.

Important

In WCF RIA Services, types deriving from Entity are not creatable. As a result, all sample data files must have their Build Action set to: DesignData and not DesignDataWithDesignTimeCreatableTypes.



Note

Blend does not support the DomainDataSource d:DesignData property. As a result, sample data applied to the DomainDataSource will not render in Blend on the art board (design surface).


<ria:DesignRIAEntitySampleDataCollection 
    xmlns:web="clr-namespace:ContosoSales.Web"
    xmlns:ria="clr-namespace:ContosoSales.SampleData">

  <web:Store City="Bellevue" StateProvince="CA" StoreID="1" StoreName="A. Datum Corporation"
            StoreImage="/ContosoSales;component/SampleDataImages/StoreFront.png" >
    <web:Store.StoreContacts>
      <web:StoreContact ContactID="55" Position="Artist" StoreID="1">
        <web:StoreContact.Contact>
          <web:Contact ContactPhoto="/ContosoSales;component/SampleDataImages/jeffhand.jpg" 
                       ContactID="55" FirstName="Alfons" LastName="Parovszky" SalesTarget="900" 
                       WorkEmail="alfons@adatum.com" WorkPhone="411" />
        </web:StoreContact.Contact>
      </web:StoreContact>
      <web:StoreContact ContactID="655" Position="Artist" Store="A. Datum Corporation" StoreID="1">
        <web:StoreContact.Contact>
          <web:Contact ContactPhoto="/ContosoSales;component/SampleDataImages/dineshku.jpg" 
                       ContactID="655" FirstName="Lori" LastName="Penor" SalesTarget="900" 
                       WorkEmail="lori@adatum.com" WorkPhone="411" />
        </web:StoreContact.Contact>
      </web:StoreContact>
    </web:Store.StoreContacts>
  </web:Store>
  <web:Store City="Bellevue" StateProvince="CA" StoreID="12" StoreName="Adventure Works"
               StoreImage="/ContosoSales;component/SampleDataImages/StoreFront.png" >
    <web:Store.StoreContacts>
      <web:StoreContact ContactID="15" Position="Sales" StoreID="2" Store="Adventure Works">
        <web:StoreContact.Contact>
          <web:Contact ContactPhoto="/ContosoSales;component/SampleDataImages/jeffhand.jpg" 
                       ContactID="15" FirstName="Justin" LastName="Harrison" SalesTarget="000" 
                       WorkEmail="justin@adventure-works.com" WorkPhone="411" />
        </web:StoreContact.Contact>
      </web:StoreContact>
      <web:StoreContact ContactID="655" Position="Artist" Store="Adventure Works" StoreID="1">
        <web:StoreContact.Contact>
          <web:Contact ContactPhoto="/ContosoSales;component/SampleDataImages/dineshku.jpg"
                       ContactID="655" FirstName="Mark" LastName="Harrington" SalesTarget="900" 
                       WorkEmail="mark@adventure-works.com" WorkPhone="411" />
        </web:StoreContact.Contact>
      </web:StoreContact>
    </web:Store.StoreContacts>
  </web:Store>
</ria:DesignRIAEntitySampleDataCollection>

Another important distinction is that the root collection must derive from List<Entity>. This is a requirement of RIA Services. Developers must create a class similar to the below class to act as a container for RIA Services sample data objects. Note, this collection does not actually care which type of entity is in the collection so long as the object derives from Entity.

namespace ContosoSales.SampleData {
    public class DesignRIAEntitySampleDataCollection : 
          List<System.ServiceModel.DomainServices.Client.Entity> {

        public DesignRIAEntitySampleDataCollection() { }
    }
}

This Store class comes from the code that Visual Studio generates in the Silverlight client application. This is contained in the hidden Generated_Code folder.

public sealed partial class Store : Entity

Connecting Sample Data

Sample data in a RIA Services application is applied to the d:DesignData property of the DomainDataSource.

<riaControls:DomainDataSource 
    SubmittedChanges="storeDomainDataSource_SubmittedChanges"  Name="storeDomainDataSource" AutoLoad="True"
    LoadedData="storeDomainDataSource_LoadedData" 
    d:DesignData="{d:DesignData Source=../SampleData/RIASampleData.xaml}"
    QueryName="GetStoresQuery" FilterOperator="Or">
    <riaControls:DomainDataSource.DomainContext>
        <my:ContactContext />
    </riaControls:DomainDataSource.DomainContext>
    ...
</riaControls:DomainDataSource>

The Home.xaml file listing is long, nested and complex so I won't display the XAML here.

The way the Home UserControl works at design-time is very similar to the previous WPF or Silverlight examples. The major difference is that the DomainDataSource is the control that receives the sample data. From here, other CollectionViewSources can "dot" into the data exposed by the Data property to populate their CollectionView and ultimately the bound UI objects.

Have a look at the below storeStoreContactsViewSource CollectionViewSource. Its Source is set to the Data.StoreContacts. In this case, Data is actually pointing to the selected Store from the left hand ListBox in the UI. The below Grid contains the data entry form on the right hand side of the form. When the ListBox selection changes the DataContext of the data entry form changes to the SelectedItem in the ListBox.

<CollectionViewSource 
    x:Key="storeStoreContactsViewSource" 
    Source="{Binding Path=Data.StoreContacts, ElementName=storeDomainDataSource}" />

 

<ListBox 
    ItemsSource="{Binding Source={StaticResource storeStoreContactsViewSource}}" 
    Name="storeContactsListBox" Style="{StaticResource ContactListBox}" />

<Grid BindingValidationError="Home_BindingValidationError" 
    DataContext="{Binding Source={StaticResource storeStoreContactsViewSource}}" Name="grid1">

This UI synchronization was accomplished without a single line of code.

Choosing Sample Data Loading Technique 

From the document you can see there are a number of ways to structure your applications and thus load sample data. One of the goals for the Design-Time Sample Data Feature for Visual Studio 2010 was to not limit or box developers in from using a technique that made business sense for the type of application they are writing. For example, many developers like the power of CollectionViewSources while other developers prefer to have their XAML files DataContext set to a ViewModel. This feature combined with the above techniques easily handles these and most other scenarios.

Using d:DesignData with a corresponding XAML Sample Data file is the recommended technique for surfacing sample data in WPF and Silverlight line of business applications. This technique surfaces design-time instances of your data classes and enables the Designer Binding Builder tooling. None of the sample data files or design-time XAML is compiled into your applications, making this technique simple and clean.

Choosing to surface sample data using d:DesignData leaves open endless possibilities for your application architecture and in-fact decouples sample data from the rest of your application.

However, as a developer you are not limited to just d:DesignData as the WPF Demo-03 Customer ViewModel demonstrated.

Comments 

Microsoft values your opinion about our products and documentation. In addition to your general feedback it is very helpful to understand:

  • How the above features enable your workflow
  • What is missing from the above features that would be helpful to you

Thank you for your feedback and have a great day,

Karl Shifflett
Expression Team

Attachment: SampleDataSolutions.zip
  • Hey Karl, top article sir!

    I was playing around with the design time viewmodel approach, and I noticed that when the viewmodel base class is marked as [Serializable] and uses an OnDeserializing attribute, it breaks the designer.

    [OnDeserializing]

    void OnDeserializing(StreamingContext context)

    {

    Initialize();

    }

    void Initialize()

    {

    notifierLock = new object();

    }

    Type 'DanielVaughan.ComponentModel.NotifyPropertyChangeBase' in assembly 'DanielVaughan.Silverlight, Version=1.3.0.0, Culture=neutral, PublicKeyToken=null' has method 'OnDeserializing' with an incorrect signature for the serialization attribute that it is decorated with. ...\ManageUsersView.xaml 11 26

    My first guess was to try changing the signature to use an object parameter (rather than StreamingContext) as with .NET 1.1 days, but to no avail.

  • Another brilliant article Karl - please, please, please keep them coming :)

  • Hello Karl,

    Thanks for this outstanding article, however we are having some issues.

    We're experiencing problems with creating sample data for classes which have no public constructor (they are created using a factory pattern). I had a look at the solutions in the SampleDataSolutions.zip file, and it seems to work there. The only difference I can spot is the fact that we're using C# projects and the SampleDataScenario projects are VB.NET projects. Could this be the cause?

    In the sample data xaml file, the xml node containing the non-create object is underlined with the message "Type 'xyz' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter." Changing the build action of this xaml data file between "DesignData" and "DesignDataWithDesignTimeCreatableTypes" does not help.

    Note: when the C# solution is loaded in Expression Blend 4, the view does display the design data correctly.

    With kind regards,

    Paul

Page 1 of 1 (3 items)
Leave a Comment
  • Please add 5 and 3 and type the answer here:
  • Post