Search code examples
c#wpfmvvmprismribbon

How do I control a WPF 4.5 Ribbons contextual tab visibility by availability of a particular control within a Prism (+ MEF) view using MVVM?


I am creating a modular desktop application using Prism 5 with MEF, WPF 4.5 and the MVVM pattern.

The application shell has a Ribbon control containing an application menu, a home tab displaying a drop-down list of available modules, a contextual tab group control intended to be activated when working with data displayed by views containing a DataGrid (ContextualTabGroupHeader="Grid Tools"). The Ribbon control also has a Prism Region (RibbonRegion) into which modules can add their own tab groups. The only other control in the shell is a Content control defining another Prism Region (MainRegion).

When a module is selected it can optionally provide views for loading into the RibbonRegion and/or MainRegion areas of the shell. I use MEF [ExportMetaData] attributes read during aggregate catalogue configuration to manage this, for example:

[ExportMetadata("ModuleDisplayName", "Example #1")]
[ExportMetadata("MainMenuView", "ExampleModule.Views.ExampleMenuView")]
[ExportMetadata("MainView", "ExampleModule.Views.ExampleTabsView")]

The module view loaded into the MainRegion could be anything capable of being added to a content control – it could, for instance, be a User Control containing a Tab control defining another module specific Prism Region into which the module could load one or more tabs containing views in response to the module ribbon tab commands. The majority of modules will have 1 or more views that can display data using a DataGrid control and I want to make a number of tools (e.g. tagging, sorting, filtering, calculating etc.) commonly available to DataGrids contained in a view that has a view model datacontext that implements a particular interface for responding to the contextual tab commands (e.g. IGridTools).

The problem: So far, all of this is working quite well: I can activate different modules and navigate views and display data in DataGrid controls – but now I have run into my problem: How do I make the ‘Grid Tools’ contextual tab visible/hidden in response to a DataGrid control becoming available/unavailable (assuming the inherited datacontext or view model implements the required interface of course)?

I can detect when a view is navigated to/from but in the case of a module using a tab control to show multiple views (which may or may not all contain a datagrid) I would also need to know when the selected tab has the requisites to display the Ribbon contextual tab. I have seen examples of using IActiveAware but generally people are happy to use the Focus/LostFocus events to change the IsActive Boolean property. The trouble is that the view containing the DataGrid may or may not have other controls that could possibly take focus (as could the main Ribbon control) but if the DataGrid is still visible I would like the contextual grid tools ribbon tab to also remain visible.


Solution

  • One possible solution would be the following:

    Considering that the Region is defined on a ContentControl, you could ask the Region for the ActiveViews, which in this case there would be only one, that is, the only Active View that is being shown.

    Therefore, you would not need the Focus/LostFocus events. The Region would take care of updating its ActiveViews list each time you navigate to a different Tab or View.

    Finally, in order to decide whether to show or hide the GridTools, you should evaluate if the Region's ActiveView contains a Grid control or not. You could achieve this by looking at UserControl's Content property.

    I hope this helped you, Regards.