• Prism: InteractionRequest and PopupModalWindowAction for WPF applications

    Published by on May 9th, 2012 2:46 pm under Prism

    5 Comments

    Hi everybody,

    As you might already know the Prism Library does not provide UI implementations for WPF interaction requests as out of the box, it only provides examples of these implementations for Silverlight, which can be used as a basis for the development of your own triggers and actions.

    Hence, I created this blog with the purpose of demonstrating a possible approach to achieve this and to show how creating similar implementations in WPF should be quite straightforward.

    Therefore, I created a sample which benefits from InteractionRequestTriggers and a custom TriggerAction<FrameworkElement> similar to the default PopupChildWindowAction class, which can be used to display a pop-up modal windows in Silverlight.

    Introduction

    The Prism documentation provides useful information on how a view model can make interaction requests directly to the view itself via an InteractionRequest object coupled with a behavior in the view. I recommend reading the following section of the Prism documentation to have a better understanding on how this works:

    As mentioned in the Prism documentation:  the standard EventTrigger provided by Expression Blend can be used to monitor an interaction request event by binding to the interaction request objects exposed by the view model. However, the Prism Library defines a custom EventTrigger, named InteractionRequestTrigger, which automatically connects to the appropriate Raised event of the IInteractionRequest interface. Once the event is raised, the InteractionRequestTrigger will invoke the specified action. As mentioned before, the library only provides the PopupChildWindowAction class for Silverlight, which displays a pop-up window to the user. By default, the specific type of pop-up window displayed by the PopupChildWindowAction class depends on the type of the context object (e.g for a Notification context object, a NotificationChildWindow is displayed, while for a Confirmation context object, a ConfirmationChildWindow is displayed). Unfortunately the ChildWindow class used by these objects returned to display as part of the trigger action is only available for Silverlight.

    Hence, when I created a custom TriggerAction similar to the PopupChildWindowAction provided with Prism, I had to change the returned type of the object to be displayed. In mi case I defined it as Window. The problem was that as a result of this change, the displayed popups would not be modals like with the ChildWindows implementations. Therefore, I also changed the way the action invokes its child window, and instead of calling the Window.Show() method in my PopupModalWindowActionBase’s Invoke method I used the Window.ShowDialog() method, which allows showing a modal window instead.

    Basically these were all the changes I needed to obtain a similar implementation to the PopupChildWindowAction. Take into account that this implementation may change depending on your personal preferences and the requirements of your scenario. Although I believe it could be considered as a starting point.

    Sample Application

    sample

    You can download the sample in my SkyDrive account, under the name “ PopupModalWindowActionSample“.

    Note that this code is provided “AS IS” with no warranties and confers no rights.

    I hope you find it useful!

    Updated 2012/05/15

    Additional Considerations

    After reviewing this approach we realize that some considerations should be taken for some scenarios. Particularly if passing a custom view using the PopupModalWindowAction‘s ChildWindow property. When doing so, you will find that you can’t show the dialog window more than once. This occurs as the view is of type window which won’t allow showing a windows once this is closed. Currently this could be achieved by creating a new custom window in the PopupModalWindowAction each time the InteractionRequest is raised, this is why the default windows implementation can be re open without problems.

    Also if you want to keep the state of the view, this can be achieved without problems by passing the same instance of the Context object when raising the InteractionRequest.

    Additionally, we have been thinking that a possible approach to reopen a custom window using the ChildWindow property may be possible passing a custom view to the ChildWindow property, and creating a new window each time the interaction is raised and use it to wrap the custom view as the content of this new window.

    Note: Also for those interested in this subject, you could check the following related blogpost which portrays a different approach, and I believe it might be helpful when showing popupwindows with custom views also using interaction requests in WPF:

    • Andy

      Thanks! That is useful, and just what I was looking for.

      Is it possible in the ViewModel that initiated the popup window to access any information that the user may enter within the dialog? For example, if the dialog allowed the user to enter his username and password, could I get this information along with the confirmation?

    • aadami

      Hi Andy,
      It’s possible to access more information, this can be achieved by passing a custom Context object when raising the InteractionRequest, as this Context will be used as the DataContext of the modal window, which will behave as the view model of this window. You could find a possible example based on this approach, in the following Codeplex thread:
      http://compositewpf.codeplex.com/discussions/355227
      Also when following this approach you should take into account the additional considerations that I have added in this post.

      Regards,

    • Simon Cui

      Hi,aadami

      when I set the CustomDialog ShowInTaskbar=”False”. and activate the Shell window. the customdialog will not show. how to solve it?

    • Simon Cui

      OK, I got it. Just set
      childWindow.Owner = Application.Current.MainWindow;
      childWindow.ShowDialog();

      Thank you

    • omar salem

      doesn’t even compile