Skip to main content

Controllers (UI Logic & Interaction)

  • 8 minutes to read

The process of building XAF applications can be divided into several steps. The first step – business model implementation, the second – default UI customization, and the third is custom feature development (to change your application’s flow and implement custom end-user interaction). For the last step, you will need to use Controllers. XAF provides a number of built-in Controllers that are used when generating the default UI. For instance, validation, navigation and search features are already included in the default UI. To implement a custom feature, you will need to create a Controller - a class derived from Controller, ViewController or WindowController class. This topic explains how to do this properly.

Note

In .NET 6 applications, the Controller’s Designer is not available because of the changes in Visual Studio’s designer architecture. You can perform related tasks in code:

Controllers Overview

Controllers serve two main purposes:

  • Perform specific actions when a Window (Frame) is created or destroyed.

    When a Window (Frame) is created, all the Controllers that are intended for it are activated, which means that their special events are raised (see Controller.Activated). You can handle these events to implement features related to the current Window (Frame) or its View. When a Window (Frame) is disposed of, its Controllers are deactivated, which means that their special event is raised (see Controller.Deactivated). This allows you to perform specific actions when closing a Window or disposing of a Frame.

  • Extend the user interface.

    In most cases, features demand end-user interaction. For this purpose, Controllers can serve as containers for Actions. Actions are objects that represent abstract UI elements, and can be displayed in a UI using actual controls: a button, combo box, submenu, etc. To respond to an end-user’s manipulations with an action control, handle the corresponding Action’s events.

As with most of the XAF entities, information on Controllers found in the application’s modules is loaded into the Application Model. You can access Controller settings in the IModelControllers node. Please refer to this node’s description for information on possible customizations.

WindowController, ViewController and Controller Classes

Physically, Controllers are Controller class descendants. Note that you will not need to create direct descendants of this class to provide Controllers for your application. Instead, you will deal with two predefined descendants - ViewController (including its generic versions: ViewController<ViewType> and ObjectViewController<ViewType, ObjectType>) and WindowController. These classes provide the Controller.Activated and Controller.Deactivated events that allow you to perform specific actions when the corresponding Window (Frame) is being created or destroyed. To access the Window (Frame) or its View in these event handlers, the ViewController class offers the Controller.Frame and ViewController.View properties. The WindowController class exposes the corresponding Window using the WindowController.Window property.

Though these two classes have a great deal in common, you should use them in different scenarios. More about this now.

View Controllers

View Controllers are intended for implementing features (filter or search features, etc.) for Views. Basically, you need to use a View Controller every time you need to implement a data-aware feature.

Actions contained in a View Controller accompany Views for which the Controller is activated. For instance, if a Controller is activated for a nested List View (List View of a collection property), its Actions will be attached to this View, not to the entire Window.

NestedFrameTemplate

View Controllers are activated for both Windows and Frames when a View is set to a Window/Frame. However, you can specify the type or ID of the View that you need to be contained in the Window or Frame. For this purpose, use the following ViewController‘s properties:

Window Controllers

Window Controllers are activated when a Window or a Frame is created, and intended for implementing features for Windows, i.e., features that are not related to specific Views. So, these features are not related to data in most cases. An example can be a Controller that changes the appearance of a navigation control in the main Window (refer to the How to: Access the Navigation Control topic to see the example). The Actions contained in Window Controllers are always displayed in a Window, no matter what View is currently displayed.

Window Controllers are activated for Windows only. You can additionally specify the Window type for which the Controller will be activated. For this purpose, use the Controller’s WindowController.TargetWindowType property. Its value can be set to Any, Main or Child. Note that XAF applications have a single Main window, which is displayed first. The rest are Child windows.

Implement Custom Controllers

If a Controller, together with its Actions, is UI-independent, it should be implemented in a Module project. At the same time, there may be a UI-specific task. In this instance, a Controller should be developed in a UI-specific Module. If your solution does not contain this project, implement it in an application project.

Controllers in XAF support dependency injection in .NET 6+ ASP.NET Core Blazor and Windows Forms applications.

Add a Controller in Design Time

You can use the ready-to-use Controller templates to create a custom Controller.

  1. In Solution Explorer, select a project to which you want to add a Controller. Right-click the Controllers folder located inside the project to invoke the context menu and select Add DevExpress Item | New Item… to invoke DevExpress Template Gallery. The following dialog will be displayed.

    Tutorial_EF_Lesson1_1

  2. Select Window Controller or View Controller, specify its name, and press the Add Item button to add a new Controller to your project.
  3. For the .NET Framework projects. Use the Controller’s Designer to both add Actions from the Toolbox and to customize your Controller’s properties using the Properties window. To invoke the Designer, you can right-click the controller file in Solution Explorer and select the View Designer context menu item.

Note that Visual Studio designer cannot be used with generic Controllers. Refer to the ViewController<ViewType> or ObjectViewController<ViewType, ObjectType> description for information on how to make the designer available. Do not forget to rebuild your solution after making changes in the Designer. Otherwise, you will not see them in the Model Editor.

Note

The Controllers folder is added to module or application projects for your convenience, to keep all your Controllers together. Meanwhile, using this folder is not a requirement. The structure of your project is fully up to you.

For the .NET Framework projects. A Controller created using a template is declared as a partial class and contains a code-behind file that will hold your customizations made using the Designer.

Add a Controller in Code

  1. Add a new class to a Module project (MySolution.Module or MySolution.***.Module). If your solution does not contain platform-specific Module projects, you can add a class to the application project. Inherit this class from one of the following classes:

  2. In the Controller’s constructor, specify the target View or Window and create Actions.

  3. Implement custom logic in the Controller event handlers.

View Controller

using DevExpress.ExpressApp;
using DevExpress.Persistent.BaseImpl;
// ...
public class MyViewController : ViewController {
    public MyViewController() : base() {
        TargetObjectType = typeof(Person);
        TargetViewType = ViewType.ListView;
    }
    protected override void OnActivated() {
        base.OnActivated();
        // Perform various tasks depending on the target View.
        View.CustomizeViewItemControl(this, MyMethod);
    }

    private void MyMethod(ViewItem viewItem) {
         // Access and customize the target View control.
    }
    protected override void OnDeactivated() {
        // Unsubscribe from previously subscribed events and release other references and resources.
        base.OnDeactivated();
    }
}

Window Controller

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.SystemModule;
// This Controller changes a caption in a main application window
public class CustomizeWindowController : WindowController {
    public CustomizeWindowController() {
        TargetWindowType = WindowType.Main;
    }
    protected override void OnActivated() {
        base.OnActivated();
        WindowTemplateController controller = Frame.GetController<WindowTemplateController>();
        controller.CustomizeWindowCaption += Controller_CustomizeWindowCaption;
    }
    private void Controller_CustomizeWindowCaption(object sender, CustomizeWindowCaptionEventArgs e) {
        e.WindowCaption.Text = "My Custom Caption";
    }
    protected override void OnDeactivated() {
        base.OnDeactivated();
        WindowTemplateController controller = Frame.GetController<WindowTemplateController>();
        controller.CustomizeWindowCaption -= Controller_CustomizeWindowCaption;
    }
}

Note

CodeRush allows you to add Actions and Controllers with a few keystrokes. To learn about the Code Templates for XAF, refer to the following help topic: XAF Templates.

See Also