Communicating between views in multitab application

Topics: Prism v4 - WPF 4
Apr 10, 2013 at 1:13 PM
We have application that uses the Prism library. The application has the WorkSpace region represented with the tab control which allows opening several instances of the same view at the same time (like mdi application).

What is a way to implement the following scenario:
  1. We have SearchView which contains FilterView and ResultView child views.
  2. We have several instances of the SearchView which opened in different tabs.
  3. Since we use the view-first approach the view model will be created in background for each of views. But view models will have no relations among themselves in this case, (it seems to be my main problem).
For example if two SearchView opened, in background we have the following view model objects created:

searchViewModel1, filterViewModel1, resultViewModel1
searchViewModel2, filterViewModel2, resultViewModel2.

When user clicks the “Apply Filter” button in the first tab, the filterViewModel1 should notify the resultViewModel1 to reload data.

But I am not sure, how we can notify the resultViewModel1 only, but not the resultViewModel2?

If I will use the event aggregator, the both resultViewModel1 and resultViewModel2 will be subscribed to refresh event....

Apr 10, 2013 at 5:54 PM

Based on my understanding, EventAggregator provides a Subscription Filtering feature which can come in handy in this type of situations. However, you will need to have a shared ID between your FilterViewModel and ResultViewModel so when you Publish the event, you send that ID as part of the parameter, and then the subscribers can filter the published events using that ID. There are different ways to do this, which mostly depends on how your application is designed:

  • You can set a unique GUID when you initialize your SearchView and pass that GUID through injection to the Filter and Result view models, so they can Publish it and filter the events accordingly
  • If you have another region inside your SearchView, which contains both your FilterViewModel and ResultViewModel, you can simply set a value to that region context and use it for your event filtering
If you need more information about subscription filtering, you can visit the following section of the Prism documentation:

Hope this helps,

Federico Martinez
Apr 10, 2013 at 6:50 PM
Edited Apr 10, 2013 at 6:58 PM
Hi Federico,

Thank you very much for reply.
I also have considered the idea about shared ID to setup relation between the FilterViewModel and the ResultViewModel.

But I still can't understand how to inject it to the view models...

As far as I can understand the initialization process will be following:
  1. I call RequestNavigate to add the SearchView to the tab control ( WorkSpace region)
    As alternative I can resolve the SearchView by Unity and add it to the WorkSpace region using RegionManager .
  2. The SearchViewModel is created and injected by Unity into the SearchView.
  3. Since the SearchView has FilterView and ResultView defined the FilterView and the ResultView objects is created.
  4. The FilterViewModel and the ResultViewModel is created and injected by Unity into the FilterView and into the ResultView.
It seems I should generate ID at the step 2, when the SearchViewModel is created. But I still not sure, if the FilterViewModel and the ResultViewModel will be created by the SearchView and by the FilterView but not by the SearchViewModel, how I can access to these view models from the SearchViewModel to pass shared ID?

Are steps 3 & 4 correct? Am I doing something wrong?

I have defined the SearchView as
<DockPanel LastChildFill="True">
    <Expander Header="Search" IsExpanded="True" DockPanel.Dock="Top">
        <v:FilterView />
    <v:ResultView DockPanel.Dock="Bottom" />
Apr 11, 2013 at 5:39 PM

As a possible option to do this, you could provide the ID by raising an event through EventAggregator, so Filter and Result view models can get this ID assigned like this:

  • Subscribe to the event on both Filter and Result view models constructor and store the ID provided
public FilterViewModel(IEventAggregator eventAggregator, ....)
     //do things

     this.eventAggregator = eventAggregator;

private void StoreID(string ID)
     this.FilterID = ID;

  • In your code behind from SearchView, set your DataContext to get your SearchViewModel from ServiceLocator. This must be done after the call to InitializeComponent so Filter and Result view models will be initialized before the SearchViewModel
public SearchView()
     this.DataContext = this.ServiceLocator.Current.GetInstance<SearchViewModel>();
  • Then, in your SearchViewModel, at the end of your constructor, raise the event that will provide the ID to Filter and Result view models. This ID will be used then in Filter and Result view models to identify between them and know which of the Result views should be updated.
public SearchViewModel(IEventAggregator eventAggregator, ....)
     //do things

This way, each time you open a new Search tab, both Filter and Result views related to this tab will be assigned with a unique ID so you can use subscription filtering to determine which Result view should be updated.

Hope this helps,

Federico Martinez
Apr 15, 2013 at 11:04 AM
Hi Federico,

Excellent idea! Thank you very much!