View Management

  • 4 minutes to read

The application, built entirely according to MVVM concepts, has multiple separate Views and ViewModels, sometimes from different assemblies. When you need to navigate to a separate application module, the MVVM Framework needs to know what particular View it should display. This article demonstrates multiple approaches to pass a required View when the navigation occurs.

Below is the list of available approaches, starting from the simplest and up to in-depth mechanics that grant you full control of what is happening when the application needs to navigate to a View. You are free to choose any approach that meets your requirements.

  1. The quickest, most versatile and effective way to navigate through application Views is to mark them with the ViewType data annotation attribute. The attribute tells the framework which View is related with the target ViewModel. This approach is described in greater detail in Lesson 3 - Navigation and Services tutorial.

Despite all advantages of using the ViewType attribute, there can be certain scenarios when it's not enough. For instance, when your Views are located in separate assemblies or have custom constructors, you need full control over the navigation mechanism. In such cases, use one of the following approaches.

  1. All DevExpress navigation services use the DevExpress.Utils.MVVM.UI.IViewLocator service to find and manage required Views. You can create your own custom implementation of this service and register it (either locally or globally) to change the way it works with application Views. See the Services topic to learn how to implement and register custom services.
  2. If you do not want to implement your custom service implementations, cast your navigation service's instance to the DevExpress.Utils.MVVM.UI.IViewService interface. For instance, in code below the DocumentManagerService service is casted.

    
    var service = DevExpress.Utils.MVVM.Services.DocumentManagerService.Create(tabbedView1);
    var viewService = service as DevExpress.Utils.MVVM.UI.IViewService;
    mvvmContext1.RegisterService(service);
    

    After that, handle the QueryView event, which allows you to dynamically assign Views depending on the required view type.

    
    viewService.QueryView += (s, e) =>
    {
        if(e.ViewType == "View1")
            e.Result = new Views.View1();
        //...
    };
    

    The required view type is specified manually. For instance, you can have the following navigation ViewModel that enumerates all available Views as items within the Modules collection.

    
    public class MyNavigationViewModel {
        protected IDocumentManagerService DocumentManagerService {
            get { return this.GetService<IDocumentManagerService>(); }
        }
        //Lists all available view types
        public string[] Modules {
            get { return new string[] { "View1", "View2", "View3" }; }
        }
        //Bind this command to required UI elements to create and display a document
        public void Show(string moduleName) {
            var document = DocumentManagerService.CreateDocument(moduleName, null, this);
            if(document != null) {
                document.Title = moduleName;
                document.Show();}
        }
    }
    
  3. The previous approach is a global solution for the required task - the QueryView event fires for the entire IViewService. You can also use API provided by individual View controls, on which the DocumentManagerService is based.

    For instance, if your Views are opened as the DocumentManager's tabs, you can handle the BaseView.QueryControl event to populate these documents. The view type in this case is stored as the document's BaseDocument.ControlName property value.

    
    var service = DevExpress.Utils.MVVM.Services.DocumentManagerService.Create(tabbedView1);
    mvvmContext1.RegisterService(service);
    
    tabbedView1.QueryControl += (s, e) =>
    {
        if(e.Document.ControlName == "View 2")
            e.Control = new Views.View2();
        //...
    };