I’ve been playing around with the Silverlight 3 navigation framework some more (thanks for the comments/thoughts on the last post about sharing data).  I got a few emails about understanding how the navigation works and people coming up with interesting uses.  Let’s take a moment to explore two of these concepts: out-of-browser navigation and controlling your navigation in your app.

Navigation Basics

If you are using Visual Studio 2008 and the Silverlight 3 tools, you’ll notice that when you choose to create a new project (or perhaps you didn’t notice and this will be new to you) that you have an option to create a Silverlight Navigation Application which is a starter template for some basic navigation framework.  This isn’t required to use the navigation framework, but merely a starting point.

Silverlight Navigation Application template

Once you have this template and click on the different navigation buttons (and/or add your own as well) you’ll see that the content changes based on the event.  Additionally you should notice that the browser’s back/forward buttons integrate with this functionality and allow you to navigate back/forward using the browser controls as well, honoring the navigation context of the application.

Out-of-browser Navigation

So now you’ve finished your app, complete with navigation and also added the functionality to allow the application to be installed out-of-browser.  Yipee!  Your users install the application offline and boom, they call you and say “how do I go back to where I was?”  Well, ideally you’ve created an application that has good navigation points in it for them, but perhaps you want to add simple forward/back functionality while in out-of-browser mode similar to the in-browser buttons that come with their preferred Internet browsing software.

Guess what?  The navigation framework provides some APIs to help you that are a part of the Frame that you are navigating:

  • CanGoForward/CanGoBack
  • GoForward/GoBack

With these two you can emulate the same browser back/forward functionality.  Here’s an example using the default VS2008 navigation template.  In MainPage.xaml I’ve removed the branding information (your.application.name) and added the following (about line 30):

   1: <StackPanel Style="{StaticResource BrandingPanelStyle}" x:Name="JournalNav">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Content</span><span style="color: #0000ff">="back"</span> <span style="color: #ff0000">Style</span><span style="color: #0000ff">="{StaticResource PageLinkStyle}"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>         <span style="color: #ff0000">x:Name</span><span style="color: #0000ff">="NavBack"</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="NavBack_Click"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Content</span><span style="color: #0000ff">="forward"</span> <span style="color: #ff0000">Style</span><span style="color: #0000ff">="{StaticResource PageLinkStyle}"</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>         <span style="color: #ff0000">x:Name</span><span style="color: #0000ff">="NavFwd"</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="NavFwd_Click"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">StackPanel</span><span style="color: #0000ff">&gt;</span></pre>

The NavBack/NavFwd click functions look like this:

   1: private void NavBack_Click(object sender, RoutedEventArgs e)
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     <span style="color: #0000ff">this</span>.Frame.GoBack();</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>  </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> NavFwd_Click(<span style="color: #0000ff">object</span> sender, RoutedEventArgs e)</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span> {</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #0000ff">this</span>.Frame.GoForward();</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span> }</pre>

Now on the Frame that I’m using I added an event handler for Navigated that looks like this:

   1: private void Frame_Navigated(object sender, NavigationEventArgs e)
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     NavBack.Opacity = Frame.CanGoBack ? 1 : 0;</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>     NavFwd.Opacity = Frame.CanGoForward ? 1:0;</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span> }</pre>

And finally I’ve added a Loaded event handler to MainPage to handle the initial load:

   1: void MainPage_Loaded(object sender, RoutedEventArgs e)
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>     JournalNav.Visibility = App.Current.RunningOffline ? Visibility.Visible : Visibility.Collapsed;</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span> }</pre>

The end result is the application in-browser works fine and uses the browser software back/forward buttons.  When installed out-of-browser, you’ll notice that an application-specific “back” and “forward” links are created (only when they are applicable) and the user can still navigate the frame that way.

In browser:

Navigation in-browser

Out-of-browser:

Navigation out-of-browser

Simple enough and I would not have had to change anything about how I already used the navigation framework in my application.

Controlling your navigation history

The other comment I’ve got is if people wanted to have ultimate control over their history navigation and have some parts integrate with the browser and other parts not.  Let me introduce you to a property of Frame: JournalOwnership.  By default the setting is Automatic, which means that the frame integrates with the browser history journal.  Setting it to something else, like OwnsJournal for example, means that it will not automatically integrate and you are now responsible for that navigation. 

What this means is that you can have a frame that is independent of the browser navigation, but still leverage the power of the framework.  Let’s alter our default template and add one of our navigation pages to include it’s own navigation pages, but those we don’t want to be a part of the overall app. 

I’ve modified the MainPage to add a link to another page called SubNavigation.xaml which then looks like this:

   1: <StackPanel>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">StackPanel</span> <span style="color: #ff0000">x:Name</span><span style="color: #0000ff">="JournalNav"</span> <span style="color: #ff0000">Orientation</span><span style="color: #0000ff">="Horizontal"</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>  </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>         <span style="color: #0000ff">&lt;</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="NavButton_Click"</span> <span style="color: #ff0000">Tag</span><span style="color: #0000ff">="/Views/SubNav/SubNav1.xaml"</span> <span style="color: #ff0000">Content</span><span style="color: #0000ff">="section 1"</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>                     <span style="color: #ff0000">Style</span><span style="color: #0000ff">="{StaticResource PageLinkStyle}"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>         <span style="color: #0000ff">&lt;</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="NavButton_Click"</span> <span style="color: #ff0000">Tag</span><span style="color: #0000ff">="/Views/SubNav/SubNav2.xaml"</span> <span style="color: #ff0000">Content</span><span style="color: #0000ff">="section 2"</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>                     <span style="color: #ff0000">Style</span><span style="color: #0000ff">="{StaticResource PageLinkStyle}"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>  </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>         <span style="color: #0000ff">&lt;</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Content</span><span style="color: #0000ff">="back"</span> <span style="color: #ff0000">Style</span><span style="color: #0000ff">="{StaticResource PageLinkStyle}"</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>             <span style="color: #ff0000">x:Name</span><span style="color: #0000ff">="NavBack"</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="NavBack_Click"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>         <span style="color: #0000ff">&lt;</span><span style="color: #800000">Button</span> <span style="color: #ff0000">Content</span><span style="color: #0000ff">="forward"</span> <span style="color: #ff0000">Style</span><span style="color: #0000ff">="{StaticResource PageLinkStyle}"</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>             <span style="color: #ff0000">x:Name</span><span style="color: #0000ff">="NavFwd"</span> <span style="color: #ff0000">Click</span><span style="color: #0000ff">="NavFwd_Click"</span> <span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     <span style="color: #0000ff">&lt;/</span><span style="color: #800000">StackPanel</span><span style="color: #0000ff">&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     <span style="color: #0000ff">&lt;</span><span style="color: #800000">navigation:Frame</span> <span style="color: #ff0000">x:Name</span><span style="color: #0000ff">="SubFrame"</span> <span style="color: #ff0000">JournalOwnership</span><span style="color: #0000ff">="OwnsJournal"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>             <span style="color: #ff0000">HorizontalContentAlignment</span><span style="color: #0000ff">="Stretch"</span> <span style="color: #ff0000">Source</span><span style="color: #0000ff">="/Views/SubNav/SubNav1.xaml"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>                           <span style="color: #ff0000">VerticalContentAlignment</span><span style="color: #0000ff">="Stretch"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>                           <span style="color: #ff0000">Padding</span><span style="color: #0000ff">="15,10,15,10"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span>                           <span style="color: #ff0000">Background</span><span style="color: #0000ff">="White"</span><span style="color: #0000ff">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New', courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum19">  19:</span> <span style="color: #0000ff">&lt;/</span><span style="color: #800000">StackPanel</span><span style="color: #0000ff">&gt;</span></pre>

You’ll see it looks similar (just for demonstration purposes) and includes a Frame.  Notice the JournalOwnership property set to OwnsJournal.  Now I also have the same back/fwd links  and functions to control them (GoBack/GoForward) in this sample, but now since I (well, SubFrame) owns the journal, I’m responsible for the navigation.  So here’s what happens:

  • User navigates to app
  • User clicks “about” – browser history appended
  • User clicks “sub navigation” – browser history appended
  • Within the “sub navigation” page, user clicks “subnav 2” – browser history not updated
  • User clicks “back” within the “subnav 2” page – user is taken back to “subnav 1”

So By changing the JournalOwnership, I get the control to manage the journal navigation, but also have to remember that.

Summary

I hope these two little experiments help you look at the navigation feature in some new ways.  It’s really a great feature I’m having fun thinking about things out loud with you all and getting feedback and more ideas.  I can’t wait to see great Silverlight 3 applications built with our framework!

The code that I used for these experiments is available here: slnavexperiments1.zip.  You will need the Silverlight 3 developer tools to run this code.  You can obtain all those tools here at the Silverlight 3 beta information section.

Hope this helps!

I got an email the other day about if there was a way to pass an object between the navigation pages in Silverlight 3.  The scenario was that the developer wanted to use the same data, but represent it visually in different ways.

Silverlight 3 introduces a new navigation framework in the runtime making it easier to navigate to different areas of an application and assist in ‘deep linking’ concepts for applications.  More resources:

At first my reaction was “no, we don’t allow that easily” but then I thought about it a bit and played around with a sample in the context of this developer’s use case.  Right now, the way you can quickly pass chunks of data to another page is via query string mechanisms.  So in my code I can say:

   1: myFrame.Navigate(new Uri("/foo.xaml?customerId=1234", UriKind.Relative));

And then in the navigated page something like:

   1: string customerId = this.NavigationContext.QueryString["customerid"];

This works fine for string/simple data.  In fact I could probably serialize a simple type and send it this way as well…but I don’t think that was the desired intent of this developer.  But if you think about the concept of the Frame, then you can start thinking about DataBinding techniques and how we can use the Frame as our container.  Allow me to think out loud…

Let’s use the default Silverlight Navigation Application template in the Silverlight 3 Tools for Visual Studio.  This will give us enough stub to work with.  If you look at MainPage.xaml you’ll see that the page has one Frame element in it:

   1: <navigation:Frame x:Name="Frame" Source="/Views/HomePage.xaml"
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum2">   2:</span>       <span style="color: rgb(255,0,0)">HorizontalContentAlignment</span><span style="color: rgb(0,0,255)">="Stretch"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum3">   3:</span>       <span style="color: rgb(255,0,0)">VerticalContentAlignment</span><span style="color: rgb(0,0,255)">="Stretch"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum4">   4:</span>       <span style="color: rgb(255,0,0)">Padding</span><span style="color: rgb(0,0,255)">="15,10,15,10"</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum5">   5:</span>       <span style="color: rgb(255,0,0)">Background</span><span style="color: rgb(0,0,255)">="White"</span><span style="color: rgb(0,0,255)">/&gt;</span></pre>

This is the core element that is going to receive navigation commands and change its content based on those commands.  Now in the Loaded event handler of MainPage, let’s grab some data.  I’m using a simple class here that just iterates a Person type (mainly so I can include it in the sample easily).  My Loaded event handler now looks like this:

   1: void MainPage_Loaded(object sender, RoutedEventArgs e)
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum2">   2:</span> {</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum3">   3:</span>     People p = <span style="color: rgb(0,0,255)">new</span> People();</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum4">   4:</span>     List&lt;Person&gt; peeps = p.GetPeople();</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum5">   5:</span>  </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum6">   6:</span>     <span style="color: rgb(0,0,255)">this</span>.Frame.DataContext = peeps;</pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum7">   7:</span> }</pre>

So you can see that I’m now setting the DataContext of the Frame element to my List<Person>.  So now let’s crack open some of the other pages.  Again, remember the scenario: same data, different views.  Open the Views/HomePage.xaml and let’s show a view of just a simple list of names.  I added a ListBox and just displayed the FullName property of my data:

   1: <StackPanel> 
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum2">   2:</span>     <span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">TextBlock</span> <span style="color: rgb(255,0,0)">Text</span><span style="color: rgb(0,0,255)">="Name List"</span> <span style="color: rgb(255,0,0)">Style</span><span style="color: rgb(0,0,255)">="{StaticResource HeaderTextStyle}"</span><span style="color: rgb(0,0,255)">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum3">   3:</span>     <span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">StackPanel</span> <span style="color: rgb(255,0,0)">Style</span><span style="color: rgb(0,0,255)">="{StaticResource ContentTextPanelStyle}"</span><span style="color: rgb(0,0,255)">&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum4">   4:</span>         <span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">ListBox</span> <span style="color: rgb(255,0,0)">x:Name</span><span style="color: rgb(0,0,255)">="PeopleList"</span> <span style="color: rgb(255,0,0)">DisplayMemberPath</span><span style="color: rgb(0,0,255)">="FullName"</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum5">   5:</span>             <span style="color: rgb(255,0,0)">ItemsSource</span><span style="color: rgb(0,0,255)">="{Binding}"</span> <span style="color: rgb(0,0,255)">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum6">   6:</span>     <span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">StackPanel</span><span style="color: rgb(0,0,255)">&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum7">   7:</span> <span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">StackPanel</span><span style="color: rgb(0,0,255)">&gt;</span></pre>

Notice that there is going to be no code here in the source file for HomePage.xaml.cs – we are using the {Binding} property for the ItemsSource…essentially trickling down the DataContext from the Frame.  Remember, that HomePage.xaml is essentially a child control of the Frame so it is aware of the DataContext.  Now let’s go into AboutPage.xaml for our more detailed view, showing a DataGrid of all the elements of the data:

   1: <StackPanel>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum2">   2:</span>     <span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">TextBlock</span> <span style="color: rgb(255,0,0)">Text</span><span style="color: rgb(0,0,255)">="Detail"</span> <span style="color: rgb(255,0,0)">Style</span><span style="color: rgb(0,0,255)">="{StaticResource HeaderTextStyle}"</span><span style="color: rgb(0,0,255)">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum3">   3:</span>     <span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">TextBlock</span> <span style="color: rgb(255,0,0)">Text</span><span style="color: rgb(0,0,255)">="Detail list of members with gender."</span> </pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum4">   4:</span>             <span style="color: rgb(255,0,0)">Style</span><span style="color: rgb(0,0,255)">="{StaticResource ContentTextStyle}"</span><span style="color: rgb(0,0,255)">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum5">   5:</span>     <span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">data:DataGrid</span> <span style="color: rgb(255,0,0)">ItemsSource</span><span style="color: rgb(0,0,255)">="{Binding}"</span><span style="color: rgb(0,0,255)">/&gt;</span></pre>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: rgb(244,244,244); margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: 'Courier New',courier,monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: rgb(96,96,96)" id="lnum6">   6:</span> <span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">StackPanel</span><span style="color: rgb(0,0,255)">&gt;</span></pre>

Again, no code here to retrieve the data or wire it up – using {Binding} to the DataContext again.  So now with one data fetch and binding to our navigation context (Frame) we can re-use that same object across different views and the result shows us different levels of detail.

View 1: simple listView 2: detail list

So at least that is one thought of how to share the information.  What do you think?  Obviously it will not work in all scenarios, but also remember you can have more than one navigation frame in your application too!  Here’s the sample code for these thoughts: SilverlightApplication32.zip

Hope this helps!

here is some csharp code:

 

<UserControl.Resources>
<ResourceDictionary x:Key="Collection" >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary x:Name="dict" Source="/Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
public static T Load<T>(this string xaml) where T : UIElement
{
T child = null;

Canvas c = XamlReader.Load("<Canvas xmlns:sj='clr-namespace:Slidentity;assembly=Slidentity' "
+ "xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' "
+ "xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>"
+ xaml + "</Canvas>") as Canvas;

child = c.Children[0] as T;
c.Children.Remove(child);

return child;
}
dfad

In a few weeks I’ll be making the journey with Corrina and Arturo from ‘the states’ to Auckland, New Zealand for the WEB09 conference.  I’m honored to be joining some great folks like Ryan Stewart, Dan Rubin, Jarred Bishop and more.  I’m looking forward to learning a lot from this conference and having discussions about user experience and RIA development.

The team at WEB09 released an introductory video for the conference and I must say, someone put a lot of effort into this video: WEB09 Intro Video

I’m very much looking forward to my time at WEB09 and the time in New Zealand in general (I’ve never been, so if you have some advice, please share).  Hopefully some of you will be there and we can meet in person and chat about Silverlight! See you in a few weeks!


This work is licensed under a Creative Commons Attribution By license.

I’ve made no hiding the fact that my blog is build on Subtext and that I’m very happy with it right now.  Lately though my wife has been blogging more (that’s another story) and she also started her own business.  Being curious about all the WordPress love, I decided to start checking it out.

Thankfully, the Web Platform Installer helped me get started on WordPress without any troubles at all and I was up and running on my Windows server (I didn’t want to start another hosting account anywhere).  I have to say, I really like what WordPress has done, especially with the extensibility points and the administration options. 

That being said, I started looking at the various plugins available and was curious about anything for Silverlight…to be able to easily put Silverlight content within a post like other plugins have enabled.  Sure, it isn’t a difficult task to begin with, but sometimes different hosts/tools make it difficult for us to add <object> type content.  After some searching in the WordPress plugin library, I found one that was built back in the Silverlight 2 beta days.  The link to the author was no longer valid so I decided to create one using that as a base.

NOTE: I totally failed my Internet duties to look via any search for one…I kept my searching to the official plugin directory.  Apologies to Peter Loebel for not recognizing he also did some work, but admittedly it was also during the beta days.  I’ve credited both Peter and Juergen Oberngruberin my readme.txt for the plugin as contributors.

So after a few minutes, I was able to get it working and created the Silverlight for WordPress plugin.  It’s simple and you basically can input into your post data:

   1: [silverlight: <app>, <width>, <height>, <initParams>, <minVer>]

Where:

  • app is the URI to your Silverlight application (XAP)
  • width/height should be obvious
  • initParams will map to the initParams of your application
  • minVer maps to the minRuntimeVersion required for your app

The only parameter required is <app> and all others are optional and have defaults which you can change via the plugin settings:

Silverlight for WordPress default settings

I’ve applied yesterday to put the plugin in the official WordPress plugin directory, but haven’t heard back yet and they don’t really have any SLA.  I’m hoping to get it in soon, because they have a good discovery model for updates, etc. and authors can install in one click.  For now, I’m also going to maintain a link to the current version with release notes on my site here: Silverlight for WordPress.

UPDATE: Silverlight for WordPress is now available in the plugins directory…just search on Silverlight.

Like I said, it’s simple (and perhaps dumb to some), but I look to your input.  Hopefully some WordPress authors may be able to use it.  I know my wife’s new photography site will :-).

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.