Skip to main content
.NET 6.0+

Create Additional ListView Nodes in Code Using a Generator Updater

  • 8 minutes to read

By default, two ListView nodes are generated in the Application Model for each business class. These nodes represent a general-purpose List View, and a Lookup List View that contains fewer columns (see List View Column Generation). Often, it is required to add more List Views manually. These additional List Views can be used as View Variants, Dashboard items, etc. Typically, this task can be accomplished in the Model Editor. However, in certain scenarios, adding nodes in code may be required.

The default process of generating Views node’s child nodes is handled by the built-in ModelViewsNodesGenerator Nodes Generator. To customize this process, you should “attach” a Generator Updater class to this Generator. This topic describes how to implement a Generator Updater that creates custom ListView nodes. Additionally, an Updater that creates View Variants using these new nodes is illustrated. For details on Nodes Generators and Generator Updaters, refer to the Extend and Customize the Application Model in Code topic.

Create List Views

Let us consider the following Employee business class.

[DefaultClassOptions,ImageName("BO_Person")]
public class Employee : BaseObject {
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public string FullName {
        get { return String.Format("{0} {1}", FirstName, LastName); }
    }
    public virtual string Position { get; set; }
    public virtual string Email { get; set; }
}

// Make sure that you use options.UseChangeTrackingProxies() in your DbContext settings.

The List View generated by default for this class is illustrated below.

GeneratorUpdater_DefaultListView

This List View is defined by the Views | Employee_ListView node. Let us implement a Generator Updater that generates two additional List Views, which are:

  1. A List View with hidden FirstName and LastName columns (Employee_ListView_FewColumns);
  2. A List View where records are grouped by the Position column (Employee_ListView_Grouped).

A Generator Updater class should inherit the abstract ModelNodesGeneratorUpdater<T> class, where T is the type of the Nodes Generator to be customized. A built-in Nodes Generator that generates the Views node content is the ModelViewsNodesGenerator. The abstract ModelNodesGeneratorUpdater`1.UpdateNode method must be implemented in a custom Generator Updater. The parameter of the ModelNode type, passed to this method, represents a generated node. In our case, this node is the Views node. To add child nodes, the ModelNode.AddNode<T> method can be used. Note that the IModelObjectView.ModelClass property must be specified for each ListView node. After that, the ListView node properties can be accessed and their values can be customized. To access the Columns node, use the IModelListView.Columns property. The following snippet illustrates the AddListViewNodesGeneratorUpdater Generator Updater class.

using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Model.Core;
using DevExpress.ExpressApp.Model.NodeGenerators;
// ...
public class AddListViewNodesGeneratorUpdater : 
    ModelNodesGeneratorUpdater<ModelViewsNodesGenerator> {
    public const string FewColumnsListViewNodeIdSuffix = "_FewColumns";
    string[] columnsToHideIds = { "FirstName", "LastName" };
    public const string GroupedListViewNodeIdSuffix = "_Grouped";
    public const string GroupByColumnId = "Position";
    static Type targetType = typeof(Employee);
    public override void UpdateNode(ModelNode viewsNode) {
        AddFewColumnsListViewNode(viewsNode);
        AddGroupedListViewNode(viewsNode);
    }
    public static IModelListView GetDefaultListView(ModelNode viewsNode) {
        return viewsNode.Application.BOModel.GetClass(targetType).DefaultListView;
    }
    IModelListView AddListViewNode(ModelNode viewsNode, string listViewId) {
        IModelListView listViewNode = (IModelListView)viewsNode.AddNode<IModelListView>(listViewId);
        listViewNode.ModelClass = viewsNode.Application.BOModel.GetClass(targetType);
        return listViewNode;
    }
    void AddFewColumnsListViewNode(ModelNode viewsNode) {
        string nodeId = GetDefaultListView(viewsNode).Id + FewColumnsListViewNodeIdSuffix;
        IModelListView fewColumnsListViewNode = AddListViewNode(viewsNode, nodeId);
        IModelColumns columns = (IModelColumns)fewColumnsListViewNode.Columns;
        foreach (string columnId in columnsToHideIds) {
            columns[columnId].Index = -1;
        }
    }
    void AddGroupedListViewNode(ModelNode viewsNode) {
        string nodeId = GetDefaultListView(viewsNode).Id + GroupedListViewNodeIdSuffix;
        IModelListView groupedListViewNode =
            AddListViewNode(viewsNode, nodeId);
        IModelColumns columns = (IModelColumns)groupedListViewNode.Columns;
        columns[GroupByColumnId].GroupIndex = 1;
    }
}

You can place this class in a separate code file in the module project, or add it to the Module.cs (Module.vb) file. The implemented Generator Updater should be registered in the overridden ModuleBase.AddGeneratorUpdaters method in the following manner:

using DevExpress.ExpressApp.Model.Core;
// ...
public sealed partial class CreateNodesInCodeModule : ModuleBase {
    // ...
    public override void AddGeneratorUpdaters(ModelNodesGeneratorUpdaters updaters) {
        base.AddGeneratorUpdaters(updaters);
        updaters.Add(new AddListViewNodesGeneratorUpdater());
    }
}

After implementing and registering the Generator Updater, rebuild the solution and invoke the Model Editor. The new ListView nodes are illustrated below.

GeneratorUpdater_ModelEditor_NewNodes

Note

Your custom nodes and properties are not marked in bold font in the Model Editor, because these changes are generated in code. You can check the Model.DesignedDiffs.xafml source to ensure that it contains no customizations related to the generated nodes.

Create View Variants

Let us implement View Variants for Employee List View to make List Views created in the previous section of this topic visible in the UI. Although the View Variants are typically designed in the Model editor, it is also possible to create View Variants in code, via the Generator Updater. The Generator Updater that generates View Variants using Views created by the AddListViewNodesGeneratorUpdater is illustrated in the snippet below. The View Variants module should be added before implementing this class.

using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Model.Core;
using DevExpress.ExpressApp.Model.NodeGenerators;
using DevExpress.ExpressApp.ViewVariantsModule;
// ...
class AddViewVariantsGeneratorUpdater : ModelNodesGeneratorUpdater<ModelViewsNodesGenerator> {
    public override void UpdateNode(ModelNode viewsNode) {
        IModelView rootView = AddListViewNodesGeneratorUpdater.GetDefaultListView(viewsNode);
        IModelView fewColumnsListView = 
            (IModelView)viewsNode.GetNode(rootView.Id +
            AddListViewNodesGeneratorUpdater.FewColumnsListViewNodeIdSuffix);
        IModelView groupedListView =
            (IModelView)viewsNode.GetNode(rootView.Id +
            AddListViewNodesGeneratorUpdater.GroupedListViewNodeIdSuffix);
        AddVariant("Default", "Default", rootView, rootView, true);
        AddVariant("FewColumns", "Few Columns", rootView, fewColumnsListView, false);
        AddVariant("Grouped", "Grouped", rootView, groupedListView, false);
    }
    void AddVariant(string variantId, string caption, 
        IModelView rootView, IModelView variantView, bool isCurrent) {
        IModelVariants variants = ((IModelViewVariants)rootView).Variants;
        IModelVariant variant = variants.AddNode<IModelVariant>(variantId);
        variant.View = variantView;
        variant.Caption = caption;
        if (isCurrent) variants.Current = variant;
    }
}

This Generator Updater should also be registered in the module’s AddGeneratorUpdaters method.

public sealed partial class CreateNodesInCodeModule : ModuleBase {
    // ...
    public override void AddGeneratorUpdaters(ModelNodesGeneratorUpdaters updaters) {
        base.AddGeneratorUpdaters(updaters);
        updaters.Add(new AddListViewNodesGeneratorUpdater());
        updaters.Add(new AddViewVariantsGeneratorUpdater());
    }
}

After implementing and registering the Generator Updater, rebuild the solution and invoke the Model Editor for the module project. The new Variant nodes are illustrated below.

GeneratorUpdater_ModelEditor_NewVariants

Now you can test the implemented Views and View Variants at runtime.

Windows Forms Application

GeneratorUpdater_WinApp

ASP.NET Web Forms Application

GeneratorUpdater_WebApp

Blazor Application

GeneratorUpdater_BlazorApp

You can use a similar approach to create Generator Updaters for built-in or custom Nodes Generators.

See Also