,

Abstracting the Navigation Service

This section begins with a brief note about its inclusion. I did not intend to show the abstraction of the navigation service. When I began work on the sample for this chapter, however, and I reached the point of needing to navigate from the sign-in page to the timeline page, I felt that it would make for a nice demonstration of a custom testable navigation service.

The custom navigation service abstracts the navigation mechanism provided by the System.Windows.Controls.Frame component or the System.Windows.Navigation.NavigationService (available via the NavigationService property of the Page class).

A custom INavigationService interface is used to navigate in a UI technology agnostic manner, and it allows the class implementation of the interface to be replaced to enable unit testing of viewmodels. INavigationService contains the following three methods:

Image GoBackNavigates the application to the most recent entry in the back navigation history, or raises an exception if no entry exists

Image Navigate(Uri source)Navigates to the content specified by the uniform resource identifier (URI)

Image Navigate(string relativeUrl)Navigates to the content specified by the relative URL

Included in the downloadable sample code are two implementations of the INavigationService, which are also present and maintained in the open-source project Calcium (http://calciumsdk.net). The first implementation, named NavigationServiceWrapper, leverages the System.Windows.Navigation.NavigationService of a Page. The second implementation, named FrameNavigationService, relies on the phone app’s root Frame (see Listing 29.8). The FrameNavigationService is the implementation used in the sample for this chapter; it is the recommended implementation for use on the phone.

LISTING 29.8. FrameNavigationService Class


public class FrameNavigationService : INavigationService
{
    Frame frameUseProperty;

    Frame Frame
    {
        get
        {
            if (frameUseProperty == null)
            {
                frameUseProperty = (Frame)Application.Current.RootVisual;
            }
            return frameUseProperty;
        }
    }

    public FrameNavigationService(Frame frame)
    {
        frameUseProperty = ArgumentValidator.AssertNotNull(frame, "frame");
    }

    [InjectDependencies]
    public FrameNavigationService()
    {
        /* Intentionally left blank. */
    }

    public void GoBack()
    {
        Frame.GoBack();
    }
    public void Navigate(Uri source)
    {
        ArgumentValidator.AssertNotNull(source, "source");
        Frame.Navigate(source);
    }

    public void Navigate(string relativeUrl)
    {
        ArgumentValidator.AssertNotNull(relativeUrl, "relativeUrl");
        Frame.Navigate(new Uri(relativeUrl, UriKind.Relative));
    }
}


The INavigationService is placed in the IoC container in the App class’s InitializeContainer method, as shown:

void InitializeContainer()
{
    SimpleContainer container = new SimpleContainer();
    container.InitializeServiceLocator();
    ...
    Dependency.Register<INavigationService, FrameNavigationService>(true);
}

The InjectDependencies attribute, on the FrameNavigationService parameterless constructor, indicates to the dependency injection system that it should use that particular constructor when instantiating the class.

In the Twitter timeline viewer sample for this chapter, the TwitterSignInViewModel class uses the INavigationService to navigate to the TimelineView page. TwitterSignInViewModel relies on a UriMapping to navigate to the page. The URI mapping is located in the App.xaml file of the project and causes the root frame of the app to direct to TwitterTimelineView.xaml whenever an attempt is made to navigate to a URI beginning with /TwitterTimeline/. See the following excerpt from the App.xaml file:

<phone:PhoneApplicationFrame.UriMapper>
    <navigation:UriMapper>
        <navigation:UriMapper.UriMappings>
            <navigation:UriMapping Uri="/TwitterTimeline/{name}"
                MappedUri="/DataDrivenApps/TwitterExample
                            /TwitterTimelineView.xaml?name={name}" />
        </navigation:UriMapper.UriMappings>
    </navigation:UriMapper>
</phone:PhoneApplicationFrame.UriMapper>

The screen name of the Twitter user is passed using a query string parameter called name.

By abstracting the INavigationService you increase the reusability of your viewmodel code, and it enables you to coordinate navigation via viewmodel logic. This alleviates the logic fragmentation that can occur when relying on the view to perform navigation.

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

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