The navigation framework

The navigation framework was first introduced in Silverlight 3. This framework is based on the concept of having a frame that displays pages and takes care of the whole navigating process from one page to another. The navigation framework supports many of the modern concepts of navigation, such as back and forward navigation, journal histories, and deep linking. The easiest way to create an application that uses the navigation framework is to select the Silverlight Navigation Application template while creating a new Silverlight project. Go ahead and create a new Silverlight project with the Silverlight Navigation Application template and name it Chapter2-Navigation.

As you look at the solution explorer, you may notice that the structure of this application is different from the one we are used to. It has a Views directory, which holds several XAML files, and the MainPage.xaml file already has some code inside of it. In a navigation application, the MainPage.xaml file, which we are used to working with as the main page of our application is nothing more than a Frame control and a Grid control to host the upper banner. You can think of this upper banner area as an ASP.NET master page—no matter what page you navigate to on your site, the upper part stays the same, so your application has a consistent feeling and style among all its pages. Before we explore the new MainPage.xaml page, go ahead and build the application. Once you have finished, run the application, and you should get the result, as shown in the following screenshot:

The navigation framework

A few things to notice about this application are as follows:

  • The end of the URL address corresponds to the currently selected page
  • The navigation buttons on the right-hand side are also synchronized with the URL and page

Click on the about button on the right-hand side of the navigation menu. You should see how the ending of the URL now points to the about page and the title in the browser tab changes to about. If we click on the browser's back button at this point, we will go back to the previous page we watched (home) just like any regular website. As you can see from this simple example, Silverlight's interaction with the browser navigation is quite tight!

Adding new pages

Currently our application has only two pages—about and home. For the vast majority of cases, you will want to add additional pages to the application containing additional logic and information. Adding a page to the application requires two steps:

  1. Add a new page (view) to the Views folder.
  2. Add a link to that page in the navigation menu.

While the first step is as easy as adding a new item, the second step involves some work on the MainPage.xaml file.

To add a new page to your application, right-click on the Views directory, click on Add, and then click on New Item.

In the New Item dialog box, select the Silverlight Page template and name it NewPage.xaml. The page template derives from the navigation:Page class, and in its core is UserControl with some added support for the navigation framework.

At this moment, our new page is nothing more than a blank grid, but we will get back to it later. Right now, our users have no way to reach the new page, and in order to solve that issue, we will use a control we discussed before, the HyperlinkButton control.

Open up MainPage.xaml and look for the LinksBorder border control. As you can see, we have two HyperlinkButton controls, and a rectangle, which acts as the divider between the two buttons. To add a new button here, all we have to do is add another HyperlinkButton and Divider. Add the following code snippet just below the Divider1 rectangle:

<HyperlinkButton x:Name="NewPageLink" Style="{StaticResource LinkStyle}" NavigateUri="/NewPage" TargetName="ContentFrame" Content="new page"/>
<Rectangle x:Name="Divider2" Style="{StaticResource DividerStyle}"/>

There are a few interesting things to notice about our newly added HyperlinkButton as follows:

  • The NavigateUri property points to /NewPage when the actual page is stored at /Views/NewPage.xaml. This is handled by UriMapper, which we will discuss in a bit.
  • The TargetName property points to ContentFrame. We've mentioned this property when we discussed the HyperlinkButton control earlier in the chapter, and here you can see that other than the usual _self or _blank values, it can also accept a Frame control name. If you scroll up a bit in the MainPage.xaml file, you'll see a Frame element named ContentFrame that is used to host the pages.
  • The Style property, although not limited to the navigation framework, is used to style the different components of the page. We will discuss styling in Silverlight later on in this book.

Build and run your application, and you should see our new HyperlinkButton control in the navigation bar. Clicking on the new HyperlinkButton control will switch the active viewing page to our newly created NewPage.xaml.

Navigation events

The navigation:Page class includes four navigation-related events, as shown in the following table:

Event name

Description

OnFragmentNavigation

This event triggers when a fragment inside the application is navigated to. An example for such a case would be /Views/Customers.xaml#CustID1023. This can be considered as Silverlight's equivalent to HTML's hashtag navigation.

OnNavigatedFrom

This event triggers when a page is no longer the active page in the frame. This event is usually used when you wish to perform a final cleanup for a page.

OnNavigatingFrom

This event triggers just before a page is swapping with another page. If the criteria you specify isn't met, you can use this event to cancel navigation to a page or remind the user to save the content before continuing.

OnNavigatedTo

This event triggers when a page becomes the active page in a frame. This event is usually used instead of the Loaded event in regular non-navigational pages.

If you take a look at MainPage.xaml.cs, you'll see that you already have the event handler for OnNavigatedTo ready to be used in your page. This is the most commonly used event for page navigation as you get to work with caching retrieval, as well as perform any page initialization setup.

NavigationService

The NavigationService class is used when you wish to work with the navigation system of the hosting frame from code behind. The NavigationService class provides five useful methods for controlling navigation, as shown in the following table:

Method name

Description

GoBack

This method navigates to the previous entry in the currently active history journal. If no entry is available, an exception will be thrown.

GoForward

This method navigates to the next entry in the currently active history journal. If no entry is available, an exception will be thrown.

Navigate

This method is used to navigate to any given URI.

Refresh

This method reloads the current page.

StopLoading

This method is used to cancel any asynchronous navigation action that hasn't been processed yet.

The GoBack and GoForward methods are typically used in the full-screen applications where you might want to build your own UI for controlling navigation. The Refresh and StopLoading methods are similar to the browser's refresh and stop/cancel buttons. Navigate is used to navigate to a different page in your application. Navigating using the Navigate method will fire the navigation events at their appropriate time.

As an example of going backward using the NavigationService class, add a button to NewPage.xaml using the following line of code:

<Button Content="Back!" x:Name="backButton" Click="backButton_Click" Width="100" Height="20"/>

Switch over to the NewPage.xaml.cs file, and add the following event handler:

private void backButton_Click(object sender, RoutedEventArgs e)
{
if (NavigationService.CanGoBack)
{
NavigationService.GoBack();
}
}

In order to prevent an exception, we first check if it's possible to go back (CanGoBack) and if so, perform the action.

Build and run your application, click on the New Page button on the top-right navigation bar and then click on the new back button. You'll get right back to the page you were coming from.

Other than these methods, the NavigationService class also exposes some useful events. Three of these events are equivalent to the page navigation events we've mentioned earlier. FragmentNavigation is equivalent to Page.FragmentNavigation, Navigated is equivalent to Page.OnNavigatedFrom, and Navigating is equivalent to Page.OnNavigatingFrom.

It is more common to use the events directly exposed from the Frame class than the Page one, but it is perfectly fine to use the ones in Page if it fits your purpose better.

Other than the three equivalent methods, an additional two methods are exposed, as shown in the following table:

Event name

Description

NavigationFailed

This event is raised when the frame fails to navigate to the requested page. It provides exception information.

NavigationStopped

This event is raised when the navigation is stopped.

The UriMapper class

The UriMapper property of the Frame class is responsible for translating real URLs of views such as /Views/NewPage.xaml to a more user-friendly URL such as /NewPage.xaml.

The UriMapper class exposes the UriMapping objects, which represent a single pair of URIs to be mapped. Each of these UriMapping objects must contain the Uri property, as well as the MappedUri property.

Let's look at the default UriMapper that our page currently has:

<navigation:Frame.UriMapper>
<uriMapper:UriMapper>
<uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>
<uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>
</uriMapper:UriMapper>
</navigation:Frame.UriMapper>

The Uri property is what the UriMapper class will activate upon and the MappedUri property sets the full path to the value of the Uri property. In our example, the first UriMapper maps any blank page entry to the home page. Assuming our application resides at http://MyNavApp.com/Application.aspx, if the user visits that address, the first UriMapping will come into play and redirect the user to the home page. On the other hand, if a user visits http://MyNavApp.com/Application.aspx#/MyNewPage, the second UriMapping will come into play and redirect the application to the Views directory and the MyNewPage.xaml file. Mappings are read top to bottom, and completed when a match is hit. Also, note that UriMapping will only work when the hashtag fragment is presented in the URL address.

A common use of the UriMapper classes is to pass data from one page to another. In HTML's world, the common pattern of passing parameters is the use of query strings. A query string is basically a name/value set that comes after a question mark sign in a URL address. While we can use the same approach in Silverlight, we have got used to showing a friendlier URL to the user. Instead of showing http://MyNavApp.com/Application.aspx#/MyNewPage?UserID=50123, we can map this address to http://MyNavApp.com/Application.aspx#/MyNewPage/50123.

To do such a thing, we need to add the following UriMapper class to our application:

<uriMapper:UriMapping Uri="/MyNewPage/{UserID}" MappedUri="/Views/MyNewPage.xaml?UserID={UserID}"/>

Retrieving the UserID parameter in the target page is done using the NavigationContext object. The NavigationContext object has a QueryString property, which can be used to retrieve the query string parameter from the URL. The most common place to retrieve the query string parameter is in the OnNavigatedTo event handler. This is the first event that gets fired once the page is navigated to, so if the query string parameter is used to initialize some content on the page (for example, showing the details of a user whose ID is 50123), this would be the perfect place to retrieve it.

The code for retrieving the UserID property is as follows:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.ContainsKey("UserID"))
{
string id = NavigationContext.QueryString["UserID"];
}
}

The journal

In Silverlight, a journal is used to save the browsing history of the user, just like your browser does when you visit the pages with it. You can always go back and forth on the pages you visited during the current user session. The Frame class has a property called JournalOwnership, which lets you decide who should own the history journal. The default value of the JournalOwnership property is Automatic. This value will set the journal to the browsers if the frame is both the top-level frame and running in the browser. If the application is running out of browser or the frame is not the top-level one, the frame itself will be in charge of maintaining the history journal.

Unless you want to build a specific navigation logic that will be used with your frame, keeping the JournalOwnership property to its default value will be sufficient in most cases.

Implementing caching

Whenever you navigate to a page using the navigation framework, a new instance of the page will be created, even if you use the back button for example. If you want Silverlight to cache a certain page, you'll have to enable caching at the page level (the navigation:Page node at the top of the XAML file) using the NavigationCacheMode property. The default value of this property is Disabled, which means no caching will be happening. Other than Disabled, you can set the NavigationCacheMode to Required or Enabled. Required will always use the cached version of a page once it's been cached. Enabled will also cache the page, but when the Frame instance's cache limit (we will discuss more on that in a second) is reached, the cache will be discarded.

The Frame instance is responsible for caching the pages it loads. By default, the size of the cache limit is set to 10 pages, but it can be changed very easily using the CacheSize property. The cache is ordered in a queue—new pages are added on top of old pages and when the limit is reached, the oldest page in the queue will no longer be cached and it will be taken off the queue to make space for the cached version of the new page. Only the pages that are marked with the Enabled value for the NavigationCacheMode property are counted for the CacheSize limit. The pages marked with Required will always cache, no matter the limit size. When a cached page is dropped from the cache, it will reload from the server the next time the user hits it. In order to save logic or inputs from a page, you should override the OnNavigatedFrom event. This event fires as soon as the user navigates from one page to another page. Even if your page is cached, the navigation events will fire, so you should handle all kinds of initialization or saving processes inside those events without having to worry whether or not the page is cached.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.140.188.244