Getting Started

  • 3 minutes to read

This tutorial explains the structure of a sample Modular MDI Application which you can create with the DevExpress Template Gallery.

MVVM_MIF_template

The application consists of four projects:

  • Common - contains common interfaces and the names of regions and modules.
  • Main - contains the MainWindow and the Bootstrapper class, that composes the application on startup.
  • Modules - contains the application’s modules.
  • Tests - contains tests.

The application consists of the following modules:

Module Key View ViewModel
Main MainWindow (UserControl) MainViewModel
Module1 ModuleView (UserControl) ModuleViewModel
Module2 ModuleView (UserControl) ModuleViewModel
Module1 (Created by a target control) NavigationItem
Module2 (Created by a target control) NavigationItem

Tip

Several modules may have the same module key if you inject them in different regions.

MVVM_MIF_composite-app

The application contains the following regions:

  1. The MainWindow region - the content of the MainWindow. The only module injected here is the MainWindow module.

    <ContentControl dxmvvm:UIRegion.Region="{x:Static common:Regions.MainWindow}"/>
    
  2. The Documents region - is defined in the MainView UserControl.

    <dxdo:DocumentGroup dxmvvm:UIRegion.Region="{x:Static common:Regions.Documents}" ... />
    

    Module1 (ModuleViewModel) and Module2 (ModuleViewModel) are injected in this DocumentGroup.

  3. The Navigation region - the navigation bar on the left.

    <dxa:AccordionControl>
        <dxa:AccordionItem dxmvvm:UIRegion.Region="{x:Static common:Regions.Navigation}" ...>
            ...
        </dxa:AccordionItem>
    </dxa:AccordionControl>
    

    Module1 (NavigationItem) and Module2 (NavigationItem) are injected here.

Inject Modules

You should register all modules at the application startup to access them by their names.

Manager.Register(Regions.MainWindow, new Module(AppModules.Main, MainViewModel.Create, typeof(MainView)));
Manager.Register(Regions.Navigation, new Module(AppModules.Module1, () => new NavigationItem("Module1")));
Manager.Register(Regions.Navigation, new Module(AppModules.Module2, () => new NavigationItem("Module2")));
Manager.Register(Regions.Documents, new Module(AppModules.Module1, () => ModuleViewModel.Create("Module1"), typeof(ModuleView)));
Manager.Register(Regions.Documents, new Module(AppModules.Module2, () => ModuleViewModel.Create("Module2"), typeof(ModuleView)));

To display a module, inject it in the application. The following code sample injects the Main, Module1, and Module2 modules:

Manager.Inject(Regions.MainWindow, AppModules.Main);
Manager.Inject(Regions.Navigation, AppModules.Module1);
Manager.Inject(Regions.Navigation, AppModules.Module2);

Note

You can execute the code sample above at any time, even when the MainWindow is not visible yet, and the visual tree is not exist. The MIF queues the injected modules and displays them as soon as the relevant regions are loaded.

There are no injected modules in the Documents region initially.

MVVM_MIF_empty-documents

A module are injected in the DocumentGroup when a user selects the module in the Accordion Control on the left side.

The Navigation event is used to achieve this kind of navigation.

Manager.GetEvents(Regions.Navigation).Navigation += OnNavigation;
Manager.GetEvents(Regions.Documents).Navigation += OnDocumentsNavigation;

Note

Each ModuleManager’s events are weak events.

The first event handler’s code is below.

void OnNavigation(object sender, NavigationEventArgs e) {
    if(e.NewViewModelKey == null) return;
    Manager.InjectOrNavigate(Regions.Documents, e.NewViewModelKey);
}

This event handler checks if the selected module exists and then uses the InjectOrNavigate method to navigate to the module. The first method argument specifies a region where the navigation is happened. The second method argument selects a module.

Note, that the modules registered in the Navigation region have the same keys as the modules registered in the Documents region. This allows to map NavigationItem modules to the corresponding ModuleViewModel modules easily.

InjectOrNavigate is a helper method that combines the Inject and Navigate methods functionality. If no module with a particular key has been injected before the invocation of the InjectOrNavigate method, the method first injects the provided module and then navigates it.

The following event handler displays the selected module in the navigation area at the application left:

void OnDocumentsNavigation(object sender, NavigationEventArgs e) {
    Manager.Navigate(Regions.Navigation, e.NewViewModelKey);
}

The code example above contains no check for e.NewViewModelKey because the application always displays a selected tab when running. All NavigationItem modules are injected at startup, and there is no need to inject them again inside the handler.