In the last Seattle Silverlight User Group meeting I spoke about Non-Linear Navigation in Silverlight.
This blog post is a proof-of-concept for Non-Linear Navigation in Silverlight 4 Navigation Applications. When I was first exploring this, I did not use the Navigation Application template, instead I implemented Non-Linear Navigation similar to what I did in BBQ Shack. Several friends asked me to try and use the Navigation Application template so I did.
The code in this post builds on any of the Navigation Application templates. For this post, I’m using the default template, but there are other cooler ones in the Visual Studio Code Gallery.
What is Non-Linear Navigation?
I first heard about Non-Linear Navigation in this dnrTV video that Billy Hollis did. While on a cruise to Alaska I wrote the BBQ Shack application, which is a WPF implementation of Non-Linear Navigation.
Non-Linear Navigation is one way for Silverlight line of business applications to provide users with a desktop application like experience. This would include both in-browser and out-of-browser applications.
The primary problem that is being addressed in this blog post is how to allow users to easily switch between unfinished tasks and for them to visually see what tasks they started but then navigated away from.
For example, the user is adding a new item to the system. Their boss calls them to look up history of another item. The user does not want to quit the add new item task to look up history of another item. In your current Silverlight applications, how would you handle this scenario?
Non-Linear Navigation easily enables this scenario, by allowing the user to navigate away from the task and start a new task. The original task is moved off screen but not destroyed and the task information is made visible on the UI.
In the below image, the user was working on an Inventory task, then switched to another task; in this case the About page. Notice the UI has clearly indicated to the user that they have one active Inventory task.
In the below image the user has just clicked the Inventory button at the top right and navigated to the Inventory module home page. Notice the three visual clues presented to the user.
- Top right – Inventory- (1) number is the total number of Inventory tasks open
- Left side – Item – (1) number is the total number of Item tasks open
- Right side – the active item is displayed in a list with a link to return to the task
The information surfaced about open tasks on the UI comes from a collection. This makes it very easy to have any sort of UI your designer/deviner/developer can dream up.
How is this Implemented?
When you want to provide custom page loading in a Navigation template you’ll want to implement a Frame.ContentLoader.
David Poll is the grand master of Silverlight Navigation template and custom ContentLoaders. David is the Silverlight Program Manager for Navigation and has written a lot about navigation. You can read all of David’s Navigation posts here.
David and I met several times to discuss navigation and the problem space I was exploring. He provided me super guidance on navigation in Silverlight which I appreciate very much. Thank you David!
The below XAML is familiar to Silverlight developers who have used one of the Navigation templates.
When the Frame receives a request to Navigate, it passes the heavy lifting off to the ContentLoader.
The default Navigation template does not specify a ContentLoader. If a ContentLoader is not specified, the default ContentLoader will be used. In the below XAML you can see where I have added the NonLinearNavigationContentLoader.
ContentLoaders are super cool in that you can chain them. The commented out below XAML shows how to chain ContentLoaders. The chaining of ContentLoaders allow each ContentLoader to perform an action, conclude the processing of the Navigate request or defer further processing to the next ContentLoader.
David Poll has written a lot about chaining ContentLoaders so I won’t attempt to duplicate his work in this space.
<navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}" Source="/HomeView" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed"> <navigation:Frame.ContentLoader> <!--This is where our custom Content load is added--> <navigatus_Navigation:NonLinearNavigationContentLoader> <!-- <navigatus_Navigation:NonLinearNavigationContentLoader.ContentLoader> <local:YouCanChainAnotherContentLoaderHere /> </navigatus_Navigation:NonLinearNavigationContentLoader.ContentLoader> --> </navigatus_Navigation:NonLinearNavigationContentLoader> </navigation:Frame.ContentLoader> </navigation:Frame>
Simply stated, the NonLinearNavigation ContentLoader does the following when the Frame receives a Navigate request:
- Checks if the requested Uri is in the collection of active tasks
- If not in the collection it will:
- Defers loading to the default ContentLoader (or chained ContentLoader)
- After content is loaded, it attaches a NavigateKey to the NonLinearNavigationContentLoader.NavigateKey attached property.
- If in the collection it will:
- Return the object matching the Uri to the Frame, no further processing is performed.
Kind of simple, uh?
For the MVVM folks out there, you’ll be happy that a Navigation can easily notify your ViewModel when the View is being brought into view or when its being navigated away from.
The PageBase class does implements this automatically for you. In some cases a Page may want to override the behavior.
The ViewModelBase class handles some plumbing that deriving classes can override to provide context specific actions.
In the below code snippet from the ItemMaintenanceViewModel class, we can see two overridden methods.
OnNavigatedTo either instantiates a new record or calls the business layer to load a record. Notice how it first checks to see if it already has data loaded. This would be the case when navigating back to an active task.
OnNavigatingFrom fulfills two important purposes. First notice the cancel parameter; this allows the ViewModel to opportunity to cancel a Navigation request. Second, this method populates the attached NavigateKey with the latest form data. There are many different techniques you could use to populate the NavigateKey, I’ve chosen the simplest method I could think of to illustrate concepts.
public override void OnNavigatedTo(Object param) { if (this.Item == null) { if (param is Int32) { Int32 id = (Int32)param; if (id == 0) { this.Item = new Item(); } else { this.Item = InventoryBLL.GetItem(id); if (this.Item == null) { throw new Exception(Constants.RECORD_NOT_FOUND); } } } } } public override void OnNavigatingFrom(ref Boolean cancel) { if (base.NavigateKey != null && this.Item != null) { if (this.Item.ItemID == 0) { base.NavigateKey.Mode = Constants.ADDING; } else { base.NavigateKey.Mode = Constants.EDITING; } base.NavigateKey.Key = this.Item.ItemID.ToString(); base.NavigateKey.Title = this.Item.Description; base.NavigateKey.IsChainable = true; base.NavigateKey.ApplicationSuite = Constants.APPLICATION_INVENTORY; //NavigateKey.CurrentSource is set in PageBase as it requires access //to the Navigation Service } }
Navigatus Application
I’ve broken the Navigatus Application into several assemblies to demonstrate how to have a Shell Page that hosts the application content. The actual application content comes from satellite assemblies.
Check out the About page. When you navigate to it, a counter will start incrementing. After a bit, navigate back to it, you’ll see that the counter continued to work even though the page was out of view.
The techniques discussed here open up many possibilities for Silverlight 4 line of business applications.
Download
I’ve been programming in C# since August of 2009. Most of my work from here forward will be done in C#. For my VB.NET brothers in arms, Karl has moved on to the dark side. Feel free to send me an email or comment if I need to clear up some C# code. Except for { } or ; it’s pretty much the same.
I’ve move to C so that I can pickup Objective-C and C++.
Close
I hope you can learn something from this proof-of-concept application.
I was hoping to have more time to work on a nice Silverlight line of business application but my non-work time is currently being consumed by my work on Mole 2010 and learning Windows Phone 7. In my spare time I’m reading my first C++ book. Once Mole 2010 ships, I need to finish Crank (my super cool code generation application) and then I hope to write a cool Silverlight line of business application that uses the techniques here.
I’m also hoping the community embraces navigation and develops patterns and frameworks for enabling RAD applications that empower uses of the software we write.
Have a great day,
Just a grain of sand on the worlds beaches.


Non-Linear Navigation in Silverlight 4 – Karl On WPF…
Thank you for submitting this cool story – Trackback from DotNetShoutout…
Karl,
You simply ROCKS. Great content once again. Learned lot about navigation. I was wondering whether something similiar to BBQ Shack WPF app can be done in Silverlight , where you had to do a right click on the icons and a pop up comes to select any open screens. I assume you must have demonstrated the same in your talk in Seattle Silverlight User Group. If you don’t mind can you please share that sample code with us. Also you can also look at http://www.clientui.com , they have awesome navigations controls.
You’re correct, I have a BBQ Shack type version for Silverlight and did a demo of it. I’ll add that post to my list and do it. I took the BBQ Shack code, made it better and simplified the API. I love it.
I went to http://www.clientui.com but have a few concerns. There is no company information on the site, just a download and a form.
Strange they don’t have a live preview of what I’m downloading.
Do you know how to contact them?
Cheers,
Karl
Hi Karl,
That was the product site. The company url is http://intersoftpt.com/
Thanks
Goldy
Thank you!! Checking it out now.
Cheers,
Karl
[quote]
I need to finish Crank (my super cool code generation application)
[/quote]
any details on “Crank” ship date and what is planned in beta release?
I “hope” by the end of August. “hope”.
I don’t do beta’s just releases.
Documentation will be the “thing” that will hold me up, not the software.
Cheers,
Karl
[...] Non-Linear Navigation post by Karl [...]