You’ve read the title. So, let me back up… In “Opening up Silverlight 4 Navigation: Introduction to INavigationContentLoader,” David Poll explains:
If you haven’t noticed by now (or been following my previous blog posts), I happen to really enjoy exploring the Navigation feature in Silverlight. A while back, I posted a number of workarounds and tips for some desirable scenarios using the Navigation feature in Silverlight 3. Then… I went silent. And the reason: I’ve been waiting for an extensibility point to be opened up in Silverlight navigation. In the Silverlight 4 beta, that extensibility point has arrived as the INavigationContentLoader.
Unlike David Poll, I was not in-the-loop-enough to “wait” for Silverlight Navigation to open up. I just noticed that I was unable to define
UriMapper programmatically—this discovery is reinforced by the documentation—notice that:
UriMapperconstructor takes no arguments (like, say, a collection of
This effectively implies that you must define
UriMapper in XAML. Losing precious hours of my time, I notice that:
- You ‘should’ define
App.xamlso it can recognize pages that might be loaded after initialization of the application domain.
- You can’t define
App.xamlwhen you are using a generic application loader (because the generic loader is not supposed to know about the pages it is loading).
It turns out that I need to implement
INavigationContentLoader because it has no dependency on
UriMapper (and its associated conventions) and because it is friendly to my MEF-based composition. By wildly misinterpreting the work of David Poll (and, perhaps, the life’s work of Jeffrey Richter), I actually find it useful to implement an interface with an abstract class. I call it
NavigationContentLoader. My reasons for doing this is because the
EndLoad() members of
INavigationContentLoader can have a default implementation (copied directly from David Poll). I mark methods
CanLoad() abstract—declaring the intent that these members must be implemented. This intent becomes content in
Concerns of BiggestBoxNavigationContentLoader…
INavigationContentLoader interface brings us the concept of the “current URI,” the current fragment identifier representing a resource in the Silverlight application and the “target URI,” the next fragment identifier. It follows that the
BiggestBoxNavigationContentLoader is concerned with:
- Mapping the “target URI” (of
INavigationContentLoader) to type names of pages (to be used by
- Parsing the “target URI” to map to type names of pages—and to extract parameters (user-control or packed-XAML sample names).
- ‘Caching’ “target URI” parameter (user-control or packed-XAML sample name) to be inspected by the current page during the
OnNavigatedTo()call (when the page finds a name it can use then the page loads a sample into a child window).
Supporting Deep Linking in a MEF-Composed Silverlight Application
This ‘caching’ behavior is very important because of the need to support “deep linking” into the Silverlight application. This support is challenging because a deep link can indicate a resource in the Silverlight application that is not currently available because of the asynchrony of MEF Composition. It follows that such an indicator has to be ‘cached’ until the application is composed.
It was tempting to try a simpler approach to solving this problem but these issues made such ease impossible:
- Reloading the same URI with
HtmlPage.Window.Navigate()is ignored by the current instance of
Frame.ContentLoader(which would be my
- Silverlight does not call the
Frame.Contentprogrammatically. I threw together the
IComposableViewinterface, with its
DoNavigateTo()methods in direct response to this issue by design.