1

I'm developing a WPF application with MVVM and PRISM 7.

At some places I'd like to open a new Window.xaml with the click of a button.

So I've created that Window.xaml and am calling it like so when clicking that button/command:

private void OnInstrumentFinderCommand()
{
    var instrumentfinder = new InstrumentFinderWindow();
    var result = instrumentfinder.ShowDialog();
    if (result == true)
    {
        // logic here...   
    }
}

That works fine. The InstrumentFinderWindow opens up and I can interact with it.

But this breaks the loosely coupling which I want to achieve with MVVM.

I know how to use PRISM with Views and Modules, but cannot figure out how I have to handle the Window to achieve the same result as the code above, but loosely coupled resp. not calling it directly from within a ViewModel.

Is there even a way or do I have to handle this completely different?

EDIT: I just want to make clear, that I'm asking about a way to call a System.Windows.Window a MVVM/PRISM-way. Not about a "Yes/No/Cancel" popup dialog.

FredM
  • 454
  • 9
  • 20

1 Answers1

2

Calling popup dialog in PRISM-way can be done with Interaction User Experience.

This way is thoroughly described in PRISM documentation and there are bunch of examples how to do it properly in prism samples (25-NotificationRequest, 26-ConfirmationRequest, 27-CustomContent, 28-CustomRequest).

Declare InteractionRequest<T> property in your ViewModel:

public InteractionRequest<Notification> FindInstrumentRequest { get; }

Raise request inside command

private void OnInstrumentFinderCommand() {
    FindInstrumentRequest.Raise(
        new Notification(), 
        notification =>
        {
             //the dialog shown, logic here
        });
}

Add interaction trigger to the window View

<UserControl ...
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:prism="http://prismlibrary.com/">

    <i:Interaction.Triggers>
        <prism:InteractionRequestTrigger SourceObject="{Binding FindInstrumentRequest}">
            <prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
                <prism:PopupWindowAction.WindowContent>
                    <views:InstrumentFinderWindow />
                </prism:PopupWindowAction.WindowContent>
            </prism:PopupWindowAction>
        </prism:InteractionRequestTrigger>
    </i:Interaction.Triggers>

...

</UserControl>

Implement IInteractionRequestAware interface by InstrumentFinderWindowViewModel and finish interaction with FinishInteraction invoking.

public partial class InstrumentFinderWindowViewModel: UserControl, IInteractionRequestAware
{
    private void SelectInstrument()
    {
        FinishInteraction?.Invoke();
    }

    public Action FinishInteraction { get; set; }
    public INotification Notification { get; set; }
}

You can create derived type of NotificationRequest and use it to pass data between window and dialog.

IMPORTANT ADDITION: This interaction mechanism will be removed in feature versions of PRISM. There is new way to handle dialog is being implemented now: DialogService. It is in pre-release version of PRISM library.

Aleksei Petrov
  • 936
  • 12
  • 31
  • Thanks, Aleksei. I'll have a look on the old an new approach. – FredM Mar 27 '19 at 14:18
  • Aleksei have you tried out the new DialogService yourself? – FredM Mar 27 '19 at 15:21
  • No, I haven't. I decided to stick to the old way until new service will be release in NuGet. – Aleksei Petrov Mar 27 '19 at 15:22
  • Hopefully soon. ;) Would you put my `InstrumentFinderWindow` in a PRISM module or leave it in the main project, where the main application/shell lays? – FredM Mar 27 '19 at 15:57
  • It depends on how often do I need to change without recompiling the main program. For example, if I have 2 different versions Instrument Finder Windows for different editions of the product. Or instrument finder window is an add-on, which could be shipped separately, could have many implementations by different teams and could be changed on client side. – Aleksei Petrov Mar 28 '19 at 08:35
  • That makes sense. I'm still struggling with understanding and would appreciate help from you again: in your sample code, you've used a `UserControl`. Which leads me to think, that this is implemented in a `Region` of the `Shell`. My goal was to have `Window.xaml` to be openend in a modal way. Is this possible? I havn't implemented anything yet, because I wanted to read more about it. – FredM Mar 28 '19 at 08:41
  • The XAML from my sample code is in **main window**. Anyway, instrument finder will be a UserControl, too. It will be opened in a modal way because of `IsModal="True"` in interaction trigger. Prism automatically creates window and puts UserControl you provided in it. – Aleksei Petrov Mar 28 '19 at 08:47
  • Ahh perfect! Thanks a lot! – FredM Mar 28 '19 at 08:50