共用方式為


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.

https://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

  • Anonymous
    March 06, 2011
    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 ?

  • Anonymous
    March 07, 2011
    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

  • Anonymous
    May 11, 2011
    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!

  • Anonymous
    May 11, 2011
    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

  • Anonymous
    June 06, 2011
    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?

  • Anonymous
    June 06, 2011
    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

  • Anonymous
    August 17, 2011
    The comment has been removed

  • Anonymous
    August 17, 2011
    The comment has been removed

  • Anonymous
    August 18, 2011
    The comment has been removed

  • Anonymous
    August 18, 2011
    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

  • Anonymous
    August 22, 2011
    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.