Handling Navigation Requests

0
167

In addition to invoking commands from the view, the Tailspin mobile client also triggers navigation requests from the view. These requests could be to navigate to a particular view or navigate back to the previous view. In some scenarios, for example if the application needs to navigate to a new view when a command completes, this requires the view model to send a message to the view. In other scenarios, you might want to trigger the navigation request directly from the view
without involving the view model directly. When you’re using the MVVM pattern, you want to be able to do all this without using any code-behind in the view, and without introducing any dependency on the view implementation in the view model classes.

Inside the Implementation

The following code example from the FilterSettingsView.xaml file shows two examples of initiating navigation in the sample application.

XAML
<i:Interaction.Behaviors>
<prismInteractivity:ApplicationBarButtonCommand
ButtonText=”Save” CommandBinding=”{Binding SaveCommand}”/>
<prismInteractivity:ApplicationBarButtonNavigation
ButtonText=”Cancel” NavigateTo=”#GoBack” />

</i:Interaction.Behaviors>

The first example invokes the SaveCommand command in the view model. The code that implements this command causes the application to navigate back to the previous view if the command succeeds, so in this example, the navigation is initiated from the view model. The following code example from the FilterSettingsView Model class illustrates this.

C#
public DelegateCommand SaveCommand { get; set; }

public FilterSettingsViewModel(…)
{

this.SaveCommand =
new DelegateCommand(this.Submit, () => !this.CanSubmit);

}

public void Submit()
{

this.NavigationService.GoBack();

}

public bool CanSubmit
{
get { return this.canSubmit; }
set
{
if (!value.Equals(this.canSubmit))
{
this.canSubmit = value;
this.RaisePropertyChanged(() => this.CanSubmit);
}
}
}

The second example shows how the view can initiate the navigation directly by navigating back to the previous view (in this case, the SurveyListView page) without executing a command.

Both examples use the ApplicationFrameNavigationService class shown in the following code example to perform the navigation.

C#
public class ApplicationFrameNavigationService :
INavigationService
{
private readonly PhoneApplicationFrame frame;

public ApplicationFrameNavigationService(
PhoneApplicationFrame frame)
{
this.frame = frame;
}
public bool Navigate(Uri source)
{
return this.frame.Navigate(source);
}
public void GoBack()
{
this.frame.GoBack();
}
public bool CanGoBack
{
get { return this.frame.CanGoBack; }
}
public Uri CurrentSource
{
get { return this.frame.CurrentSource; }
}
}

This class, which implements Tailspin’s INavigationService interface, uses the phone’s PhoneApplicationFrame instance to perform the navigation request for the application.

A view model can invoke the Navigate method on the Application FrameNavigationService object to cause the application to navigate to a particular view in the application or the GoBack method to return to the previous view.

The ViewModel base class maintains the INavigationService instance for all the view models, and the Funq dependency injection container is responsible for initially creating the Application FrameNavigationService object that implements this interface.

To avoid any code-behind in the view when the view initiates the navigation, the developers at Tailspin use an interaction behavior from the Prism Library. The following code example shows how the Cancel button is declared in the FilterSettingsView.xaml file.

XAML
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar …>

<shell:ApplicationBarIconButton Text=”Cancel”
IconUri=”…”/>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
<i:Interaction.Behaviors>

<prismInteractivity:ApplicationBarButtonNavigation
ButtonText=”Cancel” NavigateTo=”#GoBack” />

</i:Interaction.Behaviors>

The ApplicationBarButtonNavigation behavior object contains a reference to the view model, and the view model contains the reference to the ApplicationFrameNavigationService instance that handles the navigation request. The ApplicationBarButtonNavigation behavior object checks for the special value “#GoBack”, in which case, it uses the navigation service to navigate back to the previous view; otherwise, it uses the value of the NavigateTo attribute to identify the view to navigate to.