0
votes

I have a WPF PRISM application with regions -- Menu Region and workspace Region. When the menu is clicked appropriate view/form is opened inside workspace region. I have different modules like Employee, Organization, Finance, etc... with each module having multiple views/forms.

I have a requirement to open a view/form from Finance module as a dialog window when a button in the employee view/form (Module - Employee) is clicked.

Is there a way to achieve the same in PRISM?

[Edit 1]: The 2 modules are independent modules. I do not wish to add a reference of Finance module to Employee module. As further down I may have a requirement to show Employee as a dialog window from one or many Finance views.

2

2 Answers

1
votes

Sure - here are two ways for you to consider.

Option 1

Prism's documentation has a section on "Making a command globally available" using their CompositeCommand class. To do this, create a public static class in a common library that both assemblies can reference:

public static class GlobalCommands
{
    public static CompositeCommand ShowFinanceFormCommand = new CompositeCommand();
}

In the Finance form viewmodel, you would register your actual command (which has all the logic for showing the form) with:

public FinanceViewModel()
{
    GlobalCommands.ShowFinanceFormCommand.RegisterCommand(this.ShowFinancePopupCommand); 
}

In the employee view model, bind your button's ICommand to the ShowFinanceFormCommand composite command.

public EmployeeViewModel()
{
    this.EmployeeShowFinanceFormCommand = GlobalCommands.ShowFinanceFormCommand;
}

Option 2

If you need to broadcast events across modules in a loosely coupled fashion, use Prism's EventAggregator class. To implement this, create a ShowFinanceFormEvent in a common assembly that both can reference. In the employee viewmodel, publish an event when the button is pressed. In the finance viewmodel, subscribe to that event and react accordingly.

// This sits in a separate module that both can reference
public class ShowFinanceFormEvent : PubSubEvent<object>
{
}

public class EmployeeViewModel
{
    private readonly IEventAggregator eventAggregator;

    public EmployeeViewModel(IEventAggregator eventAggregator)
    {
        this.ShowFormCommand = new DelegateCommand(RaiseShowFormEvent);
        this.eventAggregator = eventAggregator;
    }

    public ICommand ShowFormCommand { get; }

    private void RaiseShowFormEvent()
    {
        // Notify any listeners that the button has been pressed
        this.eventAggregator.GetEvent<ShowFinanceFormEvent>().Publish(null);
    }
}

public class FinanceViewModel
{
    public FinanceViewModel(IEventAggregator eventAggregator)
    {
        // subscribe to button click events
        eventAggregator.GetEvent<ShowFinanceFormEvent>().Subscribe(this.ShowForm);

        this.ShowFinanceFormRequest = new InteractionRequest<INotification>();
    }

    public InteractionRequest<INotification> ShowFinanceFormRequest { get; }

    private void ShowForm(object src)
    {
        // Logic goes here to show the form... e.g.
        this.ShowFinanceFormRequest.Raise(
            new Notification { Content = "Wow it worked", Title = "Finance form title" });
    }
}
1
votes

Option 3, and the better option in my opinion, is just to use Prism's Navigation framework. If you need to show a dialog, then use a dialog service and simply pass the view key to the service to determine which view to show in the dialog. Since you re using unique keys instead of references, you don't have to know or care where the view exists.

I use a similar approach in my PluralSight course here:

https://app.pluralsight.com/library/courses/prism-showing-multiple-shells/table-of-contents

Check out the dialog service demo.