How To: Adding a Custom Item to the NavPanel
The Syndicated Client Experiences (SCE) Reader allows developers to create highly data driven applications. Frequently, application authors wish to add functionality that does not directly map to the feed structure. This article will show you how to add a custom section to the NavPanel as well as create a custom DataTemplate to control the associated user experience.
Motivating Scenario
Imagine that you have created a WPF version of Sudoku that you would like to add to the application (see here for an example). For the sake of the simplicity, assume that Suduko is a self contained module which imposes no data feed requirements.
Overview
Below are the required steps:
- Create a new data type
- Create a new DataTemplate
- Add a UserNavigator
Create a new data type
- Create a new class named SudokuSection
- In Solution Explorer, right click on the SceReaderSample project, click Add>>New Class
- Name the class "SudokuSection"
- Delete all the generated code and add the following to the file:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SceReader.Data;
namespace SceReaderSample
{
class SudokuSection : Section
{
//an empty constructor which passes information to the base class
public SudokuSection(string title, string guid, string webUri, DateTime publishDate, DateTime changeDate)
: base(title, guid, webUri, publishDate, changeDate)
{
}
}
}
Create a new DataTemplate
- In the SceReaderSample project, open Resources/BaseResources.xaml
- Add the following XML namespace declaration to the root ResourceDictionary element:
xmlns:local="clr-namespace:SceReaderSample"
- Add the following XAML to the
ResourceDictionary
<DataTemplate DataType="{x:Type local:SudokuSection}">
<Button>Sudoku</Button>
</DataTemplate>
What did I just do?
Navigation occurs within the application by navigating the MainContentContainer to a live CLR object. The visual representations of these objects are constructed from XAML DataTemplates defined in BaseResources.xaml. By creating a custom data type, you can also create an associated DataTemplate. Whenever the app navigates to an object of this type, it will be visualized by using this DataTemplate. If you had not created a DataTemplate for type "SudokuSection", the app would chose a DataTemplate for its base class, Section.
Add a UserNavigator
- Open Services/SampleServiceProvider.cs
- Import the following namespaces:
using Microsoft.SceReader.View;
using System.Collections.Generic;
using System.Collections.ObjectModel;
- Replace the OnInitializeViewManager method with the following code:
protected override void OnInitializeViewManager()
{
ViewManagerInternal = new SampleViewManager();
SudokuSection sudokuSection = new SudokuSection("Sudoku", "sudokuSection", "http://msn.com", DateTime.Now, DateTime.Now);
List<Navigator> customNavigators = new List<Navigator>();
customNavigators.Add(new SectionNavigator(sudokuSection, null));
ViewManager.SetUserNavigators(new ReadOnlyCollection<Navigator>(customNavigators));
}
- Compile and run your application by hitting F5
What did I just do?
As a performance optimization, the SCE Reader Sample uses Navigators as object proxies for navigation purposes. By default, the SCE Reader Sample creates a set of Navigators for all the items in the feed. It also creates a Navigator for the Reading List. To inject additional Navigator’s into the top level collection, you can set ViewManager.UserNavigators.
In the snippet above, we were able to use an existing Navigator type called SectionNavigator because the base class of SudokuSection is Section. If you wish, you may create your own Navigator subclass, but for most scenarios, SectionNavigator navigator will suffice.
Other strategies
Another approach would be to insert the SudokuSection directly into DataFeedContent.Sections. This would require you subclass NrrssToDataFeedConverter and override one or more methods (i.e. GetItemsFromNavigator). Although this is somewhat more complex, you do get navigation for free (including keyboard navigation, which is beyond the scope of this document).