With the latest release of nRoute we’ve added a trove of navigation-related features, to explain and demonstrate these features I’ve put together an end-to-end application that fronts the Netflix’s oData Catalog. And so in this post we’ll go through using these feature in a step-by-step manner to cumulatively compose a rich, extensible, and loosely-coupled application. Here is what we are going after:

View the nRoute’s Netflix App (note you can also install the application on your desktop).
Guide Scope
Right off the bat, let me be clear, this post does not show you how to consume oData services or explain how to design iPad’ish UIs or troll on the virtues of MVVM – it purely concentrates on plugging-in nRoute’s navigation and related features to compose our demo app. Familiarity with nRoute concepts is not a must, but will be much helpful. Secondly, just as I finalized this post, Netflix switched from a purely server-side paging-model to a hybrid client-server paging-model so I had to revisit the code, hence there might be a bit of mismatch from what’s shown here and the actual code.
Step 1. Application Setup
For our application we’ll split up the solution into two projects, one the main Silverlight (xap) application and the other a class library which will hold the Netflix service. And so first, in our data project we need to add a service reference to the Netfix oData Catalog.

We also need to need to add references to nRoute, so in both our Silverlight projects we add references to nRoute.Framework.dll, along with its dependencies System.Observable and System.Windows.Interactivity. And lastly you need to cross-reference the data project to the main application project.
Once we have the catalog in hand, we can wrap it and expose it as a singleton resource for use throughout our application. For those not familiar, nRoute has its own extensible DI and IoC components built-in (which as it happens, are quite similar to MEF), and below we are mapping the NetflixDataContext using the MapResource attribute (which is kind of the equivalent of the Export attribute in MEF).
1: [MapResource(InstanceLifetime.Singleton)]
2: public class NetflixDataContext : NetflixCatalog
3: {
4: public NetflixDataContext()
5: : base(new Uri("http://odata.netflix.com/Catalog/")) { }
6: }
And on the receiving end, to get access to our mapped NetflixDataContext resource you can resolve it using the ResolveConstructor attribute (which is again like the ImportingConstructor attribute in MEF).
1: [ResolveConstructor]
2: public SomeViewModel(NetflixDataContext context)
3: {
4: // or you could also procedurally get it like this
5: // var _context = ResourceLocator.GetResource<NetflixDataContext>();
6: }
Step 2. Bootstrap nRoute
Bootstrapping nRoute is quite simple, all you need to do is add a nRouteApplicationService instance to the ApplicationLifetimeObjects’ collection in app.xaml
1: <Application.ApplicationLifetimeObjects>
2: <n:nRouteApplicationService/>
3: </Application.ApplicationLifetimeObjects>
Now, nRoute’s application service also allows you to specify a site map for your application – the site maps concept is quite akin to the web-world. For our app, we’re going to use it to declare our top level categorization as navigable nodes. So, within our nRouteApplicationService we use a Xaml based provider to declare our site map inline:
1: <Application.ApplicationLifetimeObjects>
2: <n:nRouteApplicationService>
3: <n:XamlSiteMapProvider>
4: <n:SiteMap>
5: <n:SiteMap.RootNode>
6: <n:NavigationNode>
7: <n:NavigationNode Title="Genres" IconPath="Resources/Genres.png"
8: Url="Content/Netflix/Genres/"/>
9: <n:NavigationNode Title="Movies" IconPath="Resources/Movies.png"
10: Url="Content/Netflix/Movies/"/>
11: <n:NavigationNode Title="People" IconPath="Resources/People.png"
12: Url="Content/Netflix/People/"/>
13: <n:NavigationNode Title="About" IconPath="Resources/About.png"
14: Url="Content/About/"/>
15: </n:NavigationNode>
16: </n:SiteMap.RootNode>
17: </n:SiteMap>
18: </n:XamlSiteMapProvider>
19: </n:nRouteApplicationService>
20: </Application.ApplicationLifetimeObjects>
The motivation to use site maps here is to enable an Url-driven top-down structure that can cascade the content (and we will see ahead how). This also enables you easily change the application’s feature-set; for example, at a latter date if you want to add a language based listing feature, you’ll just need append the SiteMap declaration with the proper node and the application’s shell will pick it and cascade its usage.
Step 3. Shell Design
Our application’s shell is broken into four main areas, a feature selector, a content selector, a content display area, and lastly a header area with title, search, and navigation provisions.
And this translates to a grid with23 columns and 3 rows, which will feature two navigation containers – one to hold the listings and the other to hold the content. For those unfamiliar with what a navigation container is, it essentially is like a frame control within which you can navigate (think IFrame in HTML). And in nRoute we offer many different types of navigation containers, each with different use semantics.
The workflow here will be to allow selecting from various features (like genres or movies), and each feature will have a listing (like movies list or people list) that can be selected to have it detailed in the content area (like movie details or filmography of a person). So depending on the feature you select, the content will cascade through the two navigation containers – using navigation obviously. Also as we mentioned before we will source our top-level features-set from our SiteMap definition.
Step 4. Named Containers
Given we have more than one top-level navigation containers in our app, for the purposes of individually navigating into them we need to provide them application-wide identifiers. And to do so we just drag-drop the the NavigationHandler behaviour onto the containers and supply a unique handler name. As seen on the right we’ve named our listings related container “TopicContainer”, whilst the content related container is named "ContentContainer”.
Step 5. Setup MainPage’s ViewModel
Basically we create a MainPageViewModel class and furnish it with a MapViewModel attribute specifying the type of View the ViewModel relates to.
1: [MapViewModel(typeof(MainPage))]
2: public class MainPageViewModel : ViewModelBase
3: {
4: public MainPageViewModel() { ... }
5: }
And to inject the ViewModel in the View we just drag drop the BridgeViewModel behaviour – this behaviour basically resolves the ViewModel at runtime and injects it into the DataContext. Note, the UI element you drop onto the behaviour ascertains the ViewModel the runtime will resolve, so in this case (and most cases) we must drop it at the root level as we’ve associated the MainPageViewModel type with MainPage View type.
Step 6. Resolve and Hook the SiteMap
As we said our our features will be sourced via our application’s SiteMap – and we load the same asynchronously in our ViewModel and bind it to our templated ListBox. Further, we hook the SelectionChanged event to trigger a navigation in our “TopicContainer” named container.
1: <ListBox x:Name="FeaturesListBox" ... ItemsSource="{Binding FeatureNodes}">
2: <i:Interaction.Triggers>
3: <i:EventTrigger EventName="SelectionChanged">
4: <i:Interaction.Behaviors>
5: <ei:ConditionBehavior>
6: <ei:ConditionalExpression>
7: <ei:ComparisonCondition
8: LeftOperand="{Binding SelectedIndex, ElementName=FeaturesListBox}"
9: Operator="NotEqual" RightOperand="-1"/>
10: </ei:ConditionalExpression>
11: </ei:ConditionBehavior>
12: </i:Interaction.Behaviors>
13: <n:NavigateAction HandlerName="TopicContainer"
14: Url="{Binding Url, Source={Binding SelectedItem, ElementName=FeaturesListBox}}"/>
15: </i:EventTrigger>
16: </i:Interaction.Triggers>
17: </ListBox>
To trigger navigation all you need to do is to drag-drop the NavigateAction behaviour, and therein we specify three things:
- The navigation Url – i.e. where to navigate to, this as you can see above is resolved from the selected item in the ListBox (which BTW is the navigation-node from our site map)
- The navigation container – we specify this using our handler name we registered in step 4. What this tells is who should the navigation response, here we want it show in our listings area navigation container
- A trigger condition – this ensures that the navigate action can only be triggered if and only if there is a selection made – this check/condition is required because de-selection in a ListBox is technically also a selection changed event.
Just to be clear (for those weak-hearted) you don’t need to worry about the Xaml, you can do this entirely in Blend.
Step 7. Navigable Views and ViewModels
The next step is basically to create all your content/viewing pages but we’re not going to go through creating each of them; we’ll just take up an example to show how to create a navigable View and equally how to hook up its ViewModel.
Lets take up cause of showing Genres; the first thing we need to do on selection of the genres feature is to show a genres listing, thereon an user can select a particular genre and get a corresponding list of movies associated with that genre. So in our project to show the listings we create a GenresListingView UserControl and a corresponding GenresListingViewModel. Next we want to associate the GenresListingView to a pre-specified Url – we do so using either the MapNavigationContent or DefineNavigationContent attribute (note, there are other ways of specifying Url’able content but using attributes is somewhat preferred). Also it might help to understand that in nRoute attributes prefixed with “Map” suggest that the type it is applied-on is being “mapped” in its relevant context, so like below we are directly “mapping” the GenresListingViewModel as the ViewModel for the View type GenresListingView. And a “Define” prefixed attribute is just a stand-alone declaration and so the applied-to type is not directly associated with type it is declared on - which is why you can use “Define” prefixed attributes at the assembly level too. Like below in line 1 we’ve declared that the Url “Content/Netflix/Genres/” should be associated with the type GenresListingView and that has nothing directly to do with the GenresListingViewModel type (I’ve just put it here for convenience sake).
1: [DefineNavigationContent("Content/Netflix/Genres/", typeof(GenresListingView))]
2: [MapViewModel(typeof(GenresListingView))]
3: public class GenresListingViewModel : NavigationViewModelBase
4: {
5: ...
6: }
Note, defining navigable content and mapping ViewModels is not inter-dependent – which is to say you can define something as being navigable without it having a backing ViewModel (or even View) and equally so you can have View-ViewModel pairing without having them also be registered as navigable content.
Step 8. Inter Container Navigation
Once we’ve setup the ViewModel-View pairing, we should able to get listing for the genres from Netflix – as can be seen on the right. Next, we need to hook up functionality such that on selection of a genre, its associated movies should be listed in the content area. The idea is very similar what we did with the feature-bar, only here we’re going from within one container to navigating within another.
Below, we’ve rigged a trigger on SelectionChanged event which when triggered navigates to the specified Url in the “ContentContainer” named navigation container. The interesting part is we’re passing two parameters with keys “MovieTitles” and “PageTitle” to the navigated to page – we get the values from the selected item of the Genres’ ListBox. As you can tell below we are passing a list of movie-titles associated with a genre and a page-time derived from the name of the selected genre:
1: <ListBox x:Name="GenresListBox" ... ItemsSource="{Binding Genres}">
2: <i:Interaction.Triggers>
3: <i:EventTrigger EventName="SelectionChanged">
4: <n:NavigateAction HandlerName="ContentContainer" Url="Content/Netflix/Titles/" >
5: <n:DependencyParameter Key="MovieTitles"
6: Value="{Binding SelectedItem.Titles, ElementName=GenresListBox}"/>
7: <n:DependencyParameter Key="PageTitle"
8: Value="{Binding SelectedItem.Name, ElementName=GenresListBox,
9: StringFormat='Genre: {0}'}"/>
10: </n:NavigateAction>
11: </i:EventTrigger>
12: </i:Interaction.Triggers>
13: </ListBox>
And in the ViewModel we receive the passed in parameters by overriding the OnIntialize method of the NavigationViewModelBase class (this actually comes from implementing ISupportNavigationLifecycle interface, so you don’t really need to use the base class if you don’t want). Also in line 9 below, we set a Title for the page which the navigation container picks up (we’ll use this later to bind to the header). And we get the movies collection from the passed in parameters in line 10 which we then use to setup the ViewModel’s properties.
1: public class TitlesListingViewModel : NavigationViewModelBase
2: {
3: ...
4: protected override void OnIntialize(ParametersCollection state)
5: {
6: // if no data is passed in on initialization, it means it will be restored from state
7: if (!state.ContainsKey(MOVIE_TITLES_KEY)) return;
8:
9: base.Title = Convert.ToString(state[PAGE_TITLE_KEY]);
10: _titles = (DataServiceCollection<Title>)state[MOVIE_TITLES_KEY];
11: SetupTitles();
12: }
13: }
With binding in place and with a little templating, you should be able to see something like:
One other point, the “TitlesListingView” shown above is designed to be generic in a sense that any other page can navigate into it to show a list of movies – for example, to show an actor’s filmography we can navigate into page passing in a DataServiceCollection<Title> consisting of the actor’s movies along with a page title reflecting the same. So you can think of the two navigation parameters as a sort of loosely coupled contract for using the listing View.
Step 9. Enabling State Management
One of the other things we want to do is to enable back navigation so that you can backtrack your steps, and to effect that whilst maintaining the state of data we need to implement ISupportNavigationState – which has two simple calls to save and restore state.
Luckily, our ViewModel’s base class (NavigationViewModeBase type) already implements ISupportNavigationState so we just need to override the OnRestoreState and OnSaveState methods:
1: protected override void OnRestoreState(ParametersCollection state)
2: {
3: // if the movie titles are already loaded we don't load again
4: if (_titles != null) return;
5:
6: if (state.ContainsKey(MOVIE_TITLES_KEY))
7: {
8: base.Title = Convert.ToString(state[PAGE_TITLE_KEY]);
9: _titles = (DataServiceCollection<Title>)state[MOVIE_TITLES_KEY];
10: SetupTitles();
11: }
12: else
13: {
14: // inform no loaded data
15: }
16: }
Similarly, to save state we pass back a parameters collection consisting of the movie titles and the page title.
1: protected override ParametersCollection OnSaveState()
2: {
3: if (_titles != null)
4: {
5: return new ParametersCollection()
6: {
7: new Parameter(MOVIE_TITLES_KEY, _titles),
8: new Parameter(PAGE_TITLE_KEY, base.Title)
9: };
10: }
11: else
12: {
13: return null;
14: }
15: }
As a cautionary note, you should be careful about what you put in the navigation state as it extends the lifetime of the objects put into the navigation state cache – aka there is the potential of a memory-leak there. A lot of the time you can mitigate such risks by limiting the cache capacity or rather than putting the data itself in the cache one could just cache the meta-data required to retrieve the data.
Step 10. Navigating to Details Views

Next we want to be able to drill into a movie’s details; like from the listing of movies in a genre when a movie’s tile is clicked upon we navigate into the details page. Like before we use the NavigateAction behaviour and since we are navigating within the same container we don’t need to specify the handler name, we just pass the movie object as a parameter:
1: <i:Interaction.Triggers>
2: <i:EventTrigger>
3: <n:NavigateAction Url="Content/Netflix/Title/">
4: <n:DependencyParameter Key="MovieTitle" Value="{Binding}"/>
5: </n:NavigateAction>
6: </i:EventTrigger>
7: </i:Interaction.Triggers>
As a related point, above we are passing the bound movie object (Title Type) but one could have passed in the movie’s id using Url-tokens – so for example, we could have registered the detail’s view Url as “Content/Nextflix/Title/{MovieId}/”. And then in our event trigger we could have formatted the navigation Url to pass the id as part Url.
1: <i:Interaction.Triggers>
2: <i:EventTrigger EventName="MouseLeftButtonUp">
3: <n:NavigateAction Url="{Binding Id, StringFormat='Content/Netflix/Title/{0}'}"/>
4: </i:EventTrigger>
5: </i:Interaction.Triggers>
On the receiving end one would get the movie id from the passed-in parameters collection and then retrieve the movie object from the Netflix service. Such an Url based approach is particularly useful when you want to have browser-shell integration (like for back-forward navigation) or provide deep-linking within your application. The contrast between the Url and parameters based approaches here is quite similar to the GET v/s POST approaches in HTML world.
Step 11. Custom Navigation Containers using Adapters
Navigation containers are great, but they are not one-and-be-all as in nRoute you can turn just about any control into a navigation container by creating an adapter for it. For example, below is an adapter that turns a popup control to navigation container that you can navigate into.
1: public class PopupNavigationAdapterBehavior : NavigationAdapterBehaviorBase<Popup>
2: {
3: public override object Content
4: {
5: get { return this.AssociatedObject.Child; }
6: }
7:
8: protected override void OnSetNavigationContent(object content)
9: {
10: this.AssociatedObject.Child = (UIElement)content;
11: this.AssociatedObject.IsOpen = true;
12: }
13: }
Minimally to create an adapter you just need to implement INavigationHandler interface and set it as an attached property but for convince and ease-of-use sake you can create attachable behaviours-based adapters – and on clue, in nRoute we’ve got the NavigationAdapterBehaviorBase abstract class which minimally requires you to override a “Content” property that should return the current content and an “OnSetNavigationContent” method to set navigated to content. Just with that, as you can see below, we can attach the adapter to a popup control and then navigate into it.
For what’s show above we’ve hooked up a NavigationAction on the ratings text so that when clicked it navigates to the “Content/Rating/” Url into our popup. This works just like any other navigation operation, and quite importantly brings all the benefits of nRoute’s extensive navigation infrastructure.
1: <TextBlock ... Cursor="Hand">
2: <i:Interaction.Triggers>
3: <i:EventTrigger EventName="MouseLeftButtonUp">
4: <n:NavigateAction Url="Content/Rating/" HandlerName="PopupContainer"/>
5: </i:EventTrigger>
6: </i:Interaction.Triggers>
7: </TextBlock>
As mentioned earlier to rig the Popup control all we need to do is drop the adapter behaviour, plus below we also tack on the NavigationHandler behaviour to give it a globally usable identifier.
1: <Popup ... >
2: <i:Interaction.Behaviors>
3: <local_Behaviours:PopupNavigationAdapterBehavior/>
4: <n:NavigationHandlerBehavior HandlerName="PopupContainer"/>
5: </i:Interaction.Behaviors>
6: </Popup>
Above we’ve navigated into the same “PopupContainer”, just this time we’re navigating to an Url that shows a higher quality/larger size photo of the box art. And its worth mentioning that using the same technique you can navigate into a border control or a tabs control or a items control, it really offers an extensible approach to go beyond the normal a-to-b type navigation UIs.
Step 12. Communicating through Navigation Containers
To demonstrate the “communicating through” containers technique, in our app we’ve designed the search functionality in such a way that when in a particular listing mode the search would be local to that listing – like when in “Movies” listing feature then the search would look for movies and in “People” feature it would look for people. This might not be the best way to do search, but the idea is to show how we can hook into the content from the outside of the navigation container.

So in our case we want to expose a “searching per feature” functionality, as it were, for that we first formalize the contract using a simple interface called ISupportSearching (the Support prefix is consistent with other such interfaces in nRoute) – and it basically provides three things: a way to do search, clear the search, and lastly a way to know if the view is current in “search-mode” or not.

Next, in a MVVM friendly way, we implement this interface in our GenesListingViewModel (though you could implement it in the View). Next, to use it from the outside we just write a small trigger-action behaviour which when triggered hooks into the navigation container and executes the search:
1: public class SearchContainerAction : TargetedTriggerAction<NavigationContainer>
2: {
3: public string SearchText { get; set; } // this is actually a DP
4:
5: protected override void Invoke(object parameter)
6: {
7: if (this.Target == null || string.IsNullOrWhiteSpace(this.SearchText)) return;
8: var _searchSupporter = NavigationService.GetSupporter<ISupportSearching>(this.Target);
9: if (_searchSupporter != null) _searchSupporter.Search(this.SearchText);
10: }
11: }
Above there are two notables, one that this is a trigger-action behaviour targeted specifically to a NavigationContainer type and two we use the NavigationService static class’s GetSupporter method (line 8) to get the current implementation of ISupportSearching from the navigation container. Now, the GetSupporter method is nothing special, it basically looks at the current content of the container and checks to see if either the View or the ViewModel implements the specified interface (the ISupportSearching here) and returns that. And obviously if we get our “search supporter” we easily invoke the search functionality (line 9). Not to belabour the point, but the idea behind the “supporter” themed approach is to structure and formalize the interaction between the outside and (transitioning/navigating) inside of the navigation container – and within nRoute we use this for all container-content interactions (e.g. state management).
Similar to the SearchContainerAction we have the ClearSearchContainerAction behaviour that basically allows one to clear the search results from the outside again using the ISupportSearching contract. Also, the MoviesListingViewModel and the PeopleListingViewModel similarly implement the ISupportSearching interface to expose the search functionality in their own relevant way.
Step 13. Navigation Content Title

One other feature that navigation containers support is getting a “title” of the content from the navigated content. Firstly, there are two ways to set the “title” of content; one is by using a Title attached property, for example the “Genres Listing" title shown above is specified using the following Xaml:
1: <UserControl ... xmlns:n="http://nRoute/schemas/2010/xaml"
2: n:Navigation.Title="Genres Listing">
3: ...
4: </UserControl>
The other way, which is specifically designed for MVVM use, is to implement ISupportNavigationLifecyle interface – again like before for your convenience the optional NavigationViewModelBase class already implements the ISupportNavigationLifecycle interface and provides a “Title” property which we can set directly in the ViewModel like with the “UB40: Rockpalast Live” title above. And lastly, to get the active content title just access the “Title” property of navigation containers – like above in the header-area we just bind to the Title property of the two containers:
1: <TextBlock Text="{Binding Title, ElementName=browsingContainer}" ... />
Step 14. Navigation Transition Effects
One other thing we’ve done is to provide transition effects whilst navigating – for the content container we’ve put up a fade effect and for the listings part we’ve set an iPhone’ish slide-out/slide-in effect.
Setting the transition effects it quite easy; step one, customize the template, step two create a navigating-to-navigated transition for in-transition effect (i.e. for new content), and step three, specify the transition effect. Similarly, for the out-transition effect (i.e. for old content) create a *-to-Navigating transition and similarly specify the transition effect. The good thing with using VSM based effects is that they (mostly) run in the GPU which makes them relatively cheap and performant – plus you can add your own custom shader based transition effects if you like.
Step 15. Hooking in Navigation Container History

Last thing we want to hook the “Back” button to reflect where it will land up – like above it shows it will navigate back to the Steven Spielberg’s Person page. Getting this to work is quite easy really; for one, our content area container is a so-called “Browsing Navigation Container” (as it allows for navigate back and forward semantics) and its functionality is encapsulated in an IBrowsingContainer interface:
As you can guess from the above, all we need to do is to hook into the IBrowsingContainer’s BackPagesJournal and get the immediate-most entry to get the page-title to show.
1: var _previousState = this.BrowsingContainer.BackPagesJournal.FirstOrDefault();
2: var _canNavigateBack = this.BrowsingContainer.CanNavigateBack;
Similarly, we can just enable/disable the back button depending on if the browsing container can navigate back (this actually comes from ISupportDirectionalNavigation interface). Also FYI, the side panel which shows the listings is a “Stateful Container”, which does not feature back-forward semantics though it can save the navigation state and when navigating to the same page it returns the preserved state (and indeed we are using this to cache the results and page state).
Done
So there you have it, an end-to-end sample. Now, even though I’ve not managed to demonstrate each and every feature available to nRoute’s navigation framework, hopefully the broader gist of using nRoute’s navigation framework in bringing together a compose’able application is apparent.
View the nRoute’s Netflix App
Download the source from Codeplex
and you can also check-out more Samples
Acknowledgements
Uses Netflix Online oData Catalog
Toolbar Icons by Jospeh Wain
Posted by Rishi on 30-Jun-10 1:21 AM, 42 Comments