Welcome to WindowsClient.net | Sign in | Join

How To: Customizing Section Fronts

A section front provides quick access to the rest of the content in the section. Like a newspaper, the section front can be highly customized to uniquely convey your brand and content. In the Syndicated Client Experiences (SCE) Reader, section fronts are displayed by using a section front control (the SectionFrontControl class).

This article does not provide API-level documentation for the SectionFrontControl class. Instead, it provides a high-level overview so that you can customize the appearance and behavior of the control to suit your needs.

What is a section front template?

A section front template allows you to completely customize the layout and design of a section front. A collection of templates enables you to provide the user with a specific design for a range of screen sizes.

Below is an example of three templates, geared for children, that are completely different from the default set of templates provided in the SCE Reader Sample.

Below is the markup used to create the last template:

<Canvas x:Name="LayoutRoot" Background="#FFFFFFFF" Width="400" Height="100">

<Ellipse Fill="#FF9DF869" Stroke="{x:Null}" Width="24" Height="24" Canvas.Top="61.246" RenderTransformOrigin="0.833,0.667" Canvas.Left="368"/>
<Ellipse Fill="#FF9DF869" Stroke="{x:Null}" Width="16" Height="16" Canvas.Top="56.131" Canvas.Left="344"/>
<Ellipse Fill="#FF9DF869" Stroke="{x:Null}" Width="16" Height="16" Canvas.Left="364.328" Canvas.Top="36.459" />
<Grid RenderTransformOrigin="0.5,0.5" Width="215.999" Height="167.998" Canvas.Left="168" Canvas.Top="384" x:Name="G_CircleGrid">
  <Grid.RenderTransform>
    <TransformGroup>
      <ScaleTransform ScaleX="1" ScaleY="1"/>
      <SkewTransform AngleX="0" AngleY="0"/>
      <RotateTransform Angle="-0.45"/>
      <TranslateTransform X="0" Y="0"/>
    </TransformGroup>
  </Grid.RenderTransform>
</Grid>

<Rectangle RenderTransformOrigin="0.5,0.5" Fill="#FFF869F7" Stroke="{x:Null}" Width="13.658" Height="14.577" Canvas.Left="314.754" Canvas.Top="70.669">
  <Rectangle.RenderTransform>
    <TransformGroup>
      <ScaleTransform ScaleX="1" ScaleY="1"/>
      <SkewTransform AngleX="0" AngleY="0"/>
      <RotateTransform Angle="-48.46"/>
      <TranslateTransform X="0" Y="0"/>
    </TransformGroup>
  </Rectangle.RenderTransform>
</Rectangle>

<Rectangle RenderTransformOrigin="0.5,0.5" Fill="#FFF869F7" Stroke="{x:Null}" Width="13.658" Height="14.577" Canvas.Left="366.67" Canvas.Top="13.115">
  <Rectangle.RenderTransform>
    <TransformGroup>
      <ScaleTransform ScaleX="1" ScaleY="1"/>
      <SkewTransform AngleX="0" AngleY="0"/>
      <RotateTransform Angle="34.966"/>
      <TranslateTransform X="0" Y="0"/>
    </TransformGroup>
  </Rectangle.RenderTransform>
</Rectangle>

<Grid x:Name="MainStoryGrid" Width="262.294" Height="65.574" Canvas.Left="19.673" Canvas.Top="19.672" Panel.ZIndex="0">
  <Border Margin="-13.115,-13.115,-13.114,-13.115" Background="#FF3957D5" CornerRadius="25,25,25,25"/>
  <NewsReaderControls:MainStoryControl x:Name="MainStory1" Style="{StaticResource MainStoryControl_Plain}" />
</Grid>

<Path Width="72.479" Height="81.056" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FFFFFF00" Fill="#FFFFFF00" Data="F1 M 98.6575,135.898L 143.571,43.6903L 45.7529,66.2912L 164.319,120.475L 90.9436,27.7784L 98.6575,135.898 Z " RenderTransformOrigin="1.391,0.01" Canvas.Top="281.967" Canvas.Left="242.275">
  <Path.RenderTransform>
    <TransformGroup>
      <ScaleTransform ScaleX="1" ScaleY="1"/>
      <SkewTransform AngleX="0" AngleY="0"/>
      <RotateTransform Angle="120.794"/>
      <TranslateTransform X="-22.268" Y="-163.954"/>
  </TransformGroup>
  </Path.RenderTransform>
</Path>
</Canvas>

More specifically, a section front template is a SectionFrontControl. A SectionFrontControl class has no predefined look. In WPF, you specify the appearance of a control by using a ControlTemplate. Because a ControlTemplate can be composed of any other WPF controls, ControlTemplate provides a powerful mechanism for customizing the look and feel of your section fronts.

How can I specify a template for my SectionFrontControl object?

Because a ControlTemplate declaration dictates the visual appearance of your section fronts, the SCE Reader Sample provides an easy way to specify many different ControlTemplate instances for your section front. These templates are dynamically applied at runtime based on the size as well as the properties of a particular SectionFrontControl.

Why would I select templates based on size?

Providing a compelling layout across all window sizes and aspect ratios is exceptionally difficult (if not impossible) using a single ControlTemplate instance. Thus, small-scale screen size changes are handled by standard WPF layout mechanisms within each template. Large-scale changes (going from three columns to four columns, for example) are handled by swapping to a different template.

Why would I change templates based on other SectionFrontControl properties?

You may want to design different templates for different content types. For example, you might have a different collection of templates for the business, sports, and obituaries sections. In addition, you might need the flexibility to switch templates based on specific data in the section. For example, the SCE Reader Sample application employs different templates based on whether the first story of the section is associated with the main section image.

Changing templates based on size

The SectionFrontControl class derives from a base class named SizeTemplateControl. The function of SizeTemplateControl is simple: it picks and applies a ControlTemplate object based on its render size. SectionFrontControl inherits a Templates property of type SizeControlTemplateCollection. This collection might look like the following:

<SceReaderControls:SizeControlTemplateCollection x:Key="DefaultSizeControlTemplateCollection">
  <SceReaderControls:SizeControlTemplate MinWidth="0" MaxWidth="400" Template="{StaticResource SectionFront_1Col}"/>
  <SceReaderControls:SizeControlTemplate MinWidth="400" MaxWidth="650" Template="{StaticResource SectionFront_2Col}"/>
  <SceReaderControls:SizeControlTemplate MinWidth="650" MaxWidth="1000" Template="{StaticResource SectionFront_3Col}"/>
  <SceReaderControls:SizeControlTemplate MinWidth="1000" Template="{StaticResource SectionFront_4Col}"/>
</SceReaderControls:SizeControlTemplateCollection>

Note that each template in this collection can specify a MinWidth, MaxWidth, MinHeight, and MaxHeight value. The SectionFrontControl object uses these properties to select a template from this collection, based on the control’s current size.

Changing templates based on other properties

In the SCE Reader Sample application, you will notice the following code in the DefaultSectionFrontResource.xaml file:

<Style TargetType="{x:Type SceReaderControls:SectionFrontControl}">
  <Setter Property="Templates" Value="{StaticResource DefaultSizeControlTemplateCollection}"/>

The setter sets a default collection of templates for the SectionFrontControl object.

Below the setter, you will notice several triggers that bind to various properties of the SectionFrontControl instance. These triggers include setters which change entire template collections. In addition, you could use DataTrigger elements to swap template collections based on properties of the section. The following example shows a DataTrigger element with a setter:

<DataTrigger Binding="{Binding Path=Guid}" Value="Home.xml">
  <Setter Property="Templates" Value="{StaticResource CoolHomeSectionTemplateCollection}" />> </DataTrigger>

Adjusting template size thresholds

The template size thresholds can be easily modified by editing the MinWidth, MaxWidth, MinHeight, and MaxHeight properties of the SizeControlTemplate elements within the SizeControlTemplateCollection element. The default SizeControlTemplateCollection elements can be found in the Resources folder of the project in a file named DefaultSectionFrontResouces.xaml. The following example shows a declaration for the original SizeControlTemplate element:

<SceReaderControls:SizeControlTemplate MinWidth="0" MaxWidth="400" Template="{StaticResource SectionFront_1Col_Portrait}"/>
  <SceReaderControls:SizeControlTemplate MinWidth="400" MaxWidth="650" Template="{StaticResource SectionFront_2Col_Portrait}"/>

The following example shows a modified SizeControlTemplate element:

<SceReaderControls:SizeControlTemplate MinWidth="0" MaxWidth="300" Template="{StaticResource SectionFront_1Col_Portrait}"/>
  <SceReaderControls:SizeControlTemplate MinWidth="300" MaxWidth="650" Template="{StaticResource SectionFront_2Col_Portrait}"/>

In this example, the MaxWidth value of one template and the MinWidth value of the adjacent template have been altered. Thus, the transition from the first template to the second template will occur when the control is 300 pixels wide.

When adjusting the size thresholds, keep in mind the following requirements and guidelines:

  1. Every possible control size must have a corresponding template. Possible heights and width range from 0 to infinity. Thus, there must not be any gaps in the size thresholds of a given template collection.
  2. If MaxWidth is not specified, its value is assumed to be infinity.
  3. If MaxHeight is not specified, its value is assumed to be infinity.
  4. Make sure that selection thresholds do not overlap. If two thresholds map to the same size, no guarantees are made about which template will be selected.

Editing templates

SizeControlTemplate object are composed of specialized SceReader controls arranged using standard WPF layout controls. Although any WPF layout control can be used, all of the provided SizeControlTemplate objects use the WPF Grid control. Within this Grid control are several rows and columns that can contain the following SceReader controls:

  1. ImageControl – if a section has an image that is not associated with the section’s main story, the image is presented in this control.
  2. MainStoryControl – this control displays a single story. It can be used in conjunction with other MainStoryControls and StoryListPresenters to create sophisticated layouts.
  3. StoryListPresenter – This control presents story abstracts in a vertical list. It is linked to neighboring StoryListPresenter objects so that stories can overflow onto the next StoryListPresenter instance.
  4. Visual accents –the SCE Reader templates currently use only horizontal and vertical rectangles to provide rules between articles.

In addition, you can add any standard control or layout panel, as well as your own custom controls. Below, we show how these controls are composed on screen:

To modify one of the default SizeControlTemplate instances, simply edit the template’s XAML, which is in the Resources folder of the project in a file named DefaultSectionFrontResouces.xaml. Each template in the SizeControlTemplateCollection element has a unique key. The following example shows how to alter a template that has the key “SectionFront_3Col_Portrait.” This template has three columns of StoryListPresenter objects. An image appears in the top of the third column.

The following example shows the original definition.

<ControlTemplate x:Key="SectionFront_3Col_Portrait" TargetType="{x:Type SceReaderControls:SectionFrontControl}">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <SceReaderControls:ImageControl Grid.Column="4" Grid.Row="0" />
    <SceReaderControls:StoryListPresenter Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" x:Name="Presenter1" />
    <Rectangle Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Style="{StaticResource Rectangle_VerticalRule}" />
    <SceReaderControls:StoryListPresenter Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" x:Name="Presenter2" LinkTo="{Binding ElementName='Presenter1'}" />
    <Rectangle Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" Style="{StaticResource Rectangle_VerticalRule}" />
    <SceReaderControls:StoryListPresenter Grid.Column="4" Grid.Row="1" x:Name="Presenter3" LinkTo="{Binding ElementName='Presenter2'}" />
  </Grid>
</ControlTemplate>

In the following example, the template has been altered to place the image in the first column instead of the third column.

<ControlTemplate x:Key="SectionFront_3Col_Portrait" TargetType="{x:Type SceReaderControls:SectionFrontControl}">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="Auto"/>
      <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <SceReaderControls:ImageControl Grid.Column="0" Grid.ColumnSpan="1" Grid.Row="0" />
    <SceReaderControls:StoryListPresenter Grid.Column="0" Grid.Row="1" Grid.RowSpan="2" x:Name="Presenter1" />
    <Rectangle Grid.Column="1" Grid.Row="0" Grid.RowSpan="2" Style="{StaticResource Rectangle_VerticalRule}" />
    <SceReaderControls:StoryListPresenter Grid.Column="2" Grid.Row="0" Grid.RowSpan="2" x:Name="Presenter2" LinkTo="{Binding ElementName='Presenter1'}" />
    <Rectangle Grid.Column="3" Grid.Row="0" Grid.RowSpan="2" Style="{StaticResource Rectangle_VerticalRule}" />
    <SceReaderControls:StoryListPresenter Grid.Column="4" Grid.Row="1" x:Name="Presenter3" LinkTo="{Binding ElementName='Presenter2'}" />
  </Grid>
</ControlTemplate>

The images below show the effect of the change.

When you edit the ControlTemplate definitions, keep in mind the following requirements and guidelines:

  1. StoryListPresenter objects must have unique names within a single template.
  2. In order for content to spill over into subsequent StoryListPresenter instances, all StoryListPresenter instances except for the first one must be data-bound to the logically previous StoryListPresenter instance by means of the LinkTo property. The first StoryListPresenter object is typically linked to a MainStoryControl object, which displays the first story.

Customizing the look of section front specific controls

The SceReader controls (StoryListPresenter, MainStoryControl, and ImageControl) used in section fronts also have no predefined look. We have provided sample ControlTemplate definitions for each of these controls as well. Notice that these controls do not swap their templates based on size. However, it is possible to specify multiple templates for each of these controls. For example, to make the first column of stories look different from the second column of stories, you could specify different ControlTemplate definitions for the story abstracts of the corresponding StoryListPresenter objects in the first and second columns.

MainStoryControl

This control can be used to display a single story. You may use multiple MainStoryControls in a given section front. Below are screen shots of two different ControlTemplates for the MainStoryControl.

StoryListPresenter

This control presents a list of stories. You can specify a style for each of these stories as well as the separator between the stories. The style for the stories specifies one or more ControlTemplates which are selected based on story properties. Below, we show two different ControlTemplates. These templates are selected based on the presence of a thumbnail image.

Flowing stories between controls

The MainStoryControl and StoryListPresenter both implement IStoryListPresenter. This interface allows them to flow stories between other controls that implement this interface. This flowing behavior is defined by the LinkTo property. As the controls change size and display more or fewer stories, they notify their linked counterparts which then update themselves. In XAML, this linking behavior is defined as follows:

<SceReaderControls:StoryListPresenter x:Name="Presenter1" />
<SceReaderControls:StoryListPresenter x:Name="Presenter2" LinkTo="{Binding ElementName='Presenter1'}" />

Featured Item