Cancelling a Navigation Request using Prism v4 Region Navigation with Silverlight Frame Navigation


I have had inquiries from developers asking how to implement cancelling a navigation request when using Prism Region Navigation with Silverlight Frame Navigation.

This is a follow up blog post to Integrating Prism v4 Region Navigation with Silverlight Frame Navigation.  Please read this blog post if you have not already done so.

If you have not read the blog post Prism v4 Region Navigation Pipeline, please read this to get an understanding of Prism Region Navigation, the interfaces and the pipeline.  This blog post also covers IConfirmNavigationRequest in detail.

Background

When using Prism region navigation with WPF or Silverlight, developers can implement the IConfirmNavigationRequest interface and in the ConfirmNavigationRequest method, display a dialog, get a response and invoke the callback that was passed as an argument to ConfirmNavigationRequest.  This dialog does not have to be a modal or thread blocking dialog because the Prism Region Navigation pipeline is halted until the callback is invoked.

In order for a region navigation request to be cancelled in a Silverlight application that also uses the Silverlight frame navigation framework, a modal dialog is required when getting the response from the user.  This is because navigation is initiated by the Silverlight frame navigation framework and not the Prism region navigation.  Even if the Prism region navigation is used to initiate the request, the request is still routed to Silverlight frame navigation framework for processing.  The Silverlight frame navigation framework does not support halting the request like the Prism navigation API does, this is why a thread blocking dialog is required to get the input from the user before allowing the navigation request to continue processing.

Prism Documentation on Interaction Requests

Please read the following Prism documentation on Interaction Requests before proceeding.  This fully explains the concepts of the Interaction Request and I won’t repeat that content here.

http://msdn.microsoft.com/en-us/library/gg405494(v=PandP.40).aspx#UserInteractionPatterns

How to Implement Cancelling a Prism 4 Navigation Request when using Silverlight Frame Navigation

  • In the view, set up a Prism Interaction Request in the XAML
  • In the view model expose public property of type InteractionRequest<Confirmation>
  • In the view model implement IConfimNavigationRequest

The following XAML snippet is from the ItemView.xaml file.

  • The NavigationRequest property exposed on the view model
  • The MessageBoxNotificationAction is in MessageBoxNotificationAction.cs. 

 

<ie:Interaction.Triggers>
    <prism:InteractionRequestTrigger SourceObject="{Binding NavigationRequest}">
        <infra:MessageBoxNotificationAction />
    </prism:InteractionRequestTrigger>
</ie:Interaction.Triggers>

The below code snippet is from MessageBoxNotificationAction.cs.

The Silverlight MessageBox is used to get the response from the user.  The Silverlight MessageBox is a thread blocking message box.  This is required when cancelling a Silverlight Frame navigation request.  Currently, the Silverlight MessageBox is the only thread blocking message box available in Silverlight.  Unfortunately this message box can’t be styled or modified by the developer.

public class MessageBoxNotificationAction : TriggerAction<FrameworkElement> {

    protected override void Invoke(object parameter) {
        var args = parameter as InteractionRequestedEventArgs;
        if(args == null) {
            return;
        }

        var confirmation = (Confirmation)args.Context;
        MessageBoxResult result = MessageBox.Show(confirmation.Content.ToString(), confirmation.Title, MessageBoxButton.OKCancel);

        confirmation.Confirmed = result == MessageBoxResult.OK;
        args.Callback();
    }
}

The below three code snippets are from ItemViewModel.cs.

The above view XAML data binds to the below NavigationRequest property exposed on the view model.

public InteractionRequest<Confirmation> NavigationRequest { get; private set; }

The NavigationRequest property is initialized in the view model constructor.

[ImportingConstructor]
public ItemViewModel(IRegionManager regionManager) {
    _regionManager = regionManager;
    NavigationRequest = new InteractionRequest<Confirmation>();
}

The below code is the implementation for the IConfirmNavigationRequest interface. IConfirmNavigationRequest derives from the INavigationRequest interface and adds a single method ConfirmNavigationRequest.

void IConfirmNavigationRequest.ConfirmNavigationRequest(NavigationContext navigationContext, Action<Boolean> continuationCallback) {
    this.NavigationRequest.Raise(
        new Confirmation {
            Content = "Would you like to continue navigating away?",
            Title = "Navigation Confirmation"
        }, confirmation => continuationCallback(confirmation.Confirmed));
}

During the processing of the navigation request the above ConfirmNavigationRequest method will be called causing the following code to be executed:

  • Raise method on the InteractionRequest is invoked.  (NavigationRequest property exposes InteractionRequest)
  • The triggers in the XAML trigger the above MessageBoxNotificationAction.Invoke method
  • The result of the MessageBoxNotificationAction.Invoke method are returned in the Confirmation, Confirmed property
  • The Prism Region Navigation API will either cancel or continue the navigation request based on the Confirm property

Running the Sample Code

Requirements: you must download Prism 4 or later and run the RegisterPrismBinaries.bat batch file. The Prism v4 Readme covers this file in detail. If you do not want to run this batch file, you’ll need to remove and re-add the references to the Prism assemblies.

I have attached a modified version of the code that demonstrates cancelling a navigation request.  To see this in action, run the application, select Inventory in the menu bar, select an inventory item to edit, then press the Close button on the inventory item form.  A MessageBox will prompt you to continue the navigation or cancel it.

Comments

Microsoft values your opinion about our products, guidance, documentation and samples.

Thank you for your feedback and have a great day,

Karl Shifflett

Patterns & Practices Prism Team

SilverlightPrismv4IntegratedNavigationWithCancellationEnabled.zip

Comments (11)

  1. Mourad says:

    Hello,

    thanks for your work

    i got a problem when trying to compile the solution

    it says : Error Could not write lines to file "objDebugThePhoneCompany.Data.csproj.FileListAbsolute.txt". The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters. ThePhoneCompany.Data

    any idea ?

  2. Mourad,

    I've seen this error before but not with this project.

    For now, close visual studio, go to the folder where you unzipped the example code.  Change the folder name to a much shorter name, then locate the .sln file and reopen the solution.  You should be good to go.

    Karl

  3. weitzhandler says:

    Karl thanks for the great job with Prism and your posts!

    What's the most efficient way to close a View (that was RequestNavigated to) from its (or another) ViewModel or controler?

    I published the full question here: compositewpf.codeplex.com/…/251524

    Thanks!

  4. Have a look at this post;  blogs.msdn.com/…/prism-v4-region-navigation-pipeline.aspx and search for IRegionMemberLifeTime.KeepAlive.

    Implementing this interface makes it very easy to remove a view/viewmodel from the region.

    Karl

  5. Joe Kahl says:

    Hi Karl.  I am struggling to use this approach with WPF.  I have studied the Prism 4 Quickstarts View-Switching Navigation.  I set mine up the same and it does not work.  Not only is there no ChildWindow in WPF, but when I hard code the Action<bool> to false : continuationCallback(false); the navigation still continues!  I created a solution using the MVVM InTheBox template.  I studied it.  I created a UserControl to cover the entire application window, not just the active view.  I cannot figure out how to call it.  The MVVM InTheBox example is not enough.  The navigation is too fake.  The navigation buttons are on the same view and there is no request to go anywhere.  I have tried to figure this out.  Can you help me?

  6. Joe,

    WPF does not require this.  The code in this example is only for the Silverlight Frame Navigation API.

    Have you looked at this WPF application?  blogs.msdn.com/…/patterns-and-practices-2010-symposium-content.aspx

    This should help you get your applicaiton set up.  

    This blog post covers the cancellation: blogs.msdn.com/…/prism-v4-region-navigation-pipeline.aspx

    I'm also preparing another end-to-end example that will be published the last week of June.

    Best,

    Karl

  7. Bishman says:

    I have a quick question, if I wanted to style the Message box, or use a childwindow I created and styled with the MessageBoxNotificationAction how would I go about doing that.

    Thank you so much in advance.

  8. Bishman,

    You can't style the message box.  If you use the child window you can have any UI you want since you are controlling which child window gets created.  Does that help?

    Karl

  9. Bishman says:

    First off thanks for your prompt reply.

    So if I understand you correctly Karl, in the MessageBoxNotificationAction  instead of calling message box, call a childwindow, but where would that child window live, would it be in the client, or in the common project?

    I have the sample you provided implemented in my code and i am able to generate the messagebox on navigation, so I just need to know where to store the child window.

    Also, will the same thing apply to error message?  Meaning, if I want to have a common error messagebox/Childwindow to show for the errors in the application how would I go about doing that?

    Thanks a lot.

  10. Bishman,

    I'm on vacation now.  Please post your question here:  compositewpf.codeplex.com/discussions

    You'll get a very prompt response from our Prism Support Engineers.

    Best,

    Kar

  11. Bishman says:

    Hello Karl,

    Thank you so much for responding to me while you are on vacation, hope you are having a good time… 🙂

    I posted my question to codeplex.  But I have not received an answer yet.

    When you return from vacation, do you mind responding to my question.

    Again, thank you in advance.