How To: Customizing the Section Front UI by Extending the Data Feed
Introduction
Developers frequently ask how to adapt the look and feel of section fronts based on the content of the feed. There are two approaches.
In the first approach, the Style section of the SectionFront control has a DataTrigger element which looks for a specific property (for example, the Guid property) and selects an appropriate template collection (such as SportTemplates). This approach is simple to implement. However, because template selection is hard coded, it lacks flexibility.
In the second approach, the data feed itself contains information about which set of templates to use in order to display a particular section. This is the scenario that will be illustrated here. However, the point is to illustrate various extensibility mechanisms in the Syndicated Client Experiences (SCE) Reader. These principles can be applied to many other aspects of the SCE Reader.
Steps
The basic steps used below can be used in many other scenarios. Here is an outline of the steps:
- Extend the data feed
- Extend the data model
- Extend the data converters
- Extend sample service provider
- Modify UI
Disclaimer
The feed contains support for arbitrary key/value pairs (<rx:properties>). Using these would remove the requirement to do steps 1-4. For an example, see the "kicker" property in the sample feed and UI.
Nevertheless, the point of this exercise is to show the extensibility pattern which may be used when the key/value pair approach is not appropriate.
Extend the data feed
The Syndicated Client Experiences (SCE) Reader is data driven. Thus, extending the data feed is frequently the best place to start customizing the SCE Reader. To begin, you will introduce a new element into the data feed. To maintain compliance with the RSS 2.0 spec, your custom elements should be defined in a custom namespace. For simplicity, the example extension illustrated here uses the rx namespace (feel free to do so as well):
<item>
…
<rx:TemplateType>TypeA</rx:TemplateType>
…
<:/item>
Extend the data model
Derive a custom section from DataFeedSection and add a new property named TemplateType. The custom section’s constructor accepts an extra argument named TemplateType. The rest of the constructor’s arguments are just passed to the base class constructor.
class CustomSection : DataFeedSection
{
public string TemplateType
{
get { return _templateType; }
protected set { _templateType = value; }
}
public CustomSection(string title, string guid, string webUri, DateTime publishDate, DateTime changeDate, IDictionary<string, string> properties, IList<string> storyGuids, IList<string> subSectionGuids, SectionImageReference mainImageReference, string TemplateType)
: base(title, guid, webUri, publishDate, changeDate, properties storyGuids, subSectionGuids, mainImageReference)
{
_templateType = TemplateType;
}
string _templateType;
}
Extend the data converters
You must now get the data from the extended feed into the extended data object. This can be achieved by overriding the appropriate data converter, as shown in the following example.
class CustomNrssToDataFeedConverter : NrrssToDataFeedConverter
{
protected override DataFeedSection GetSectionFromNavigator(XPathNavigator navigator, string source)
{
DataFeedSection temp = base.GetSectionFromNavigator(navigator, source);
return CreateCustomSection(temp, navigator);
}
CustomSection CreateCustomSection(DataFeedSection temp, XPathNavigator navigator)
{ //parse the navigator and create a custom section here }
}
Extend sample service provider
The SCE Reader sample application is already configured with a sample service provider. You need to override the RegisterConverters method on ServiceProvider. After calling the base RegisterConverters method, you unregister the old DataFeedContent converter and register the new one in its place. This is done as follows:
protected override void RegisterConverters()
{
base.RegisterConverters();
ConverterManager.UnRegister(typeof(XPathDocument), typeof(DataFeedContent));
ConverterManager.Register(typeof(XPathDocument), typeof(DataFeedContent), new CustomNrssToDataFeedConverter());
}
Modify UI
The SCEReaderSample project contains a sample implementation for section front templates. In the Style section for SectionFrontControl in the DefaultSectionFrontResources.xaml file, add the following DataTrigger object:
<DataTrigger Binding="{Binding Path=TemplateType}" Value="SpecialTemplateA">
<Setter Property="Templates" Value=""{StaticResource SpecialTemplateCollectionA}" />
</DataTrigger>
In this data trigger, you apply a specific template collection when TemplateType is set to “SpecialTemplateA.” Naturally, “SpecialTemplateCollectionA” would also need to be defined.