воскресенье, 7 февраля 2010 г.

DXPrinting: using DataTemplateSelector with SimpleLink

Printing data with a SimpleLink is straightforward: define a DataTemplate that represents a data item layout, specify the number of items and call the CreateDocument method.

But what if your data consists of objects of different types? How do you print them when each type has its own layout? This is where DataTemplateSelector comes to help.

Consider that we have a collection of CalendarEntry objects:

CalendarEntryClassHierarchy
Let's start with creating a DataTemplate for each calendar entry type. To keep things simple, I'm using a very simple layout:

<DataTemplate x:Key="anniversary">
  <Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Margin="0,0,0,5" Background="LightBlue">
    <StackPanel Margin="5">
      <TextBlock Text="{Binding Date, StringFormat='Date: {0}'}" />
      <TextBlock Text="{Binding Occasion, StringFormat='Occasion: {0}'}" />
    </StackPanel>
  </Border>
</DataTemplate>
<DataTemplate x:Key="todo">
  <Border BorderBrush="Black" BorderThickness="1" CornerRadius="0" Margin="0,0,0,5" Background="LightGray">
    <StackPanel Margin="5">
      <TextBlock Text="{Binding DueDate, StringFormat='Due Date: {0}'}" />
      <TextBlock Text="{Binding Subject, StringFormat='Subject: {0}'}" />
    </StackPanel>
  </Border>
</DataTemplate>
<DataTemplate x:Key="meeting">
  <Border BorderBrush="Black" BorderThickness="1" CornerRadius="0" Margin="0,0,0,5" Background="LightGreen">
    <StackPanel Margin="5">
      <TextBlock Text="{Binding Subject, StringFormat='Subject: {0}'}" />
      <TextBlock Text="{Binding Location, StringFormat='Location: {0}'}" />
      <TextBlock Text="{Binding Start, StringFormat='Start: {0}'}" />
      <TextBlock Text="{Binding End, StringFormat='End: {0}'}" />
    </StackPanel>
  </Border>
</DataTemplate>

Now when we have our data templates, let's create a data template selector. Instead of writing an ad-hoc selector simply for this example, I've built a reusable DetailTemplateSelector class. It provides the Type and DataTemplate properties, which allows you to configure it as follows:

<local:DetailTemplateSelector x:Key="calendarEntryTemplateSelector">
  <local:DetailTemplateSelector.Templates>
    <DataTemplate x:Key="{x:Type local:ToDoNote}">
      <!-- ToDoNote template definition -->
    </DataTemplate>
    <DataTemplate x:Key="{x:Type local:Anniversary}">
      <!-- Anniversary template definition -->
    </DataTemplate>
    <DataTemplate x:Key="{x:Type local:Meeting}">
      <!-- Meeting template definition -->
    </DataTemplate>
  </local:DetailTemplateSelector.Templates>
</local:DetailTemplateSelector>

And now the final trick: the SimpleLink class doesn't have any property to set a data template selector. We use a workaround: our detail template is a ContentPresenter and its ContentTemplateSelector property is set to the DetailTemplateSelector object:

<DataTemplate x:Key="calendarEntry">
  <ContentPresenter ContentTemplateSelector="{StaticResource calendarEntryTemplateSelector}" />
</DataTemplate>

Now we can use a link to build a document and show its print preview:

UsingDataTemplateSelectorWithSimpleLink

Easy enough, isn’t it?

Комментариев нет:

Отправить комментарий

Random thoughts, ideas and questions on .NET development

Постоянные читатели