Skip to main content
.NET 6.0+

How to: Extend and Access the Application Model Nodes from Controllers

  • 7 minutes to read

Follow the instructions below to extend the Application Model in the following two ways:

  • Add the IsGroupFooterVisible property to Views | <ListView> nodes. If set to true, the corresponding List View displays a Group Footer.
  • Add the GroupFooterSummaryType property to column nodes (ListView | Columns | Column). This property specifies group summary type for the corresponding column.

For more information on how to extend the Application Model, refer to the following topic: Extend and Customize the Application Model in Code.

View Example: How to Extend the Application Model

Common Steps

Implement interfaces that expose the IsGroupFooterVisible and GroupFooterSummaryType properties:

using DevExpress.Data;
using System.ComponentModel;
//...
public interface IModelListViewExtender {
    bool IsGroupFooterVisible { get; set; }
}
public interface IModelColumnExtender {
    [DefaultValue(SummaryItemType.None)]
    SummaryItemType GroupFooterSummaryType { get; set; }
}

Override the ModuleBase.ExtendModelInterfaces method of your base Module to extend the Application Model with declared interfaces:

using DevExpress.ExpressApp.Model;
// ...
public sealed partial class ExtendModelModule : ModuleBase {
    // ...
    public override void ExtendModelInterfaces(ModelInterfaceExtenders extenders) {
        base.ExtendModelInterfaces(extenders);
        extenders.Add<IModelListView, IModelListViewExtender>();
        extenders.Add<IModelColumn, IModelColumnExtender>();
    }
}

WinForms-Specific Steps

Inherit a WinGroupFooterViewController from the ViewController<ListView> type in the Windows Forms Module. This base class choice ensures the Controller activates in List Views only.

Override the protected OnViewControlsCreated method. If the IsGroupFooterVisible property is set to true for the current List View, display the group footer.

Note that users can change column summary types in the UI. Handle the View.ModelSaved event to save these changes to the Application Model when users close the current List View.

using System;
using DevExpress.Data;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Win.Editors;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Columns;
//...
public class WinGroupFooterViewController : ViewController<ListView> {
    private void View_ModelSaved(object sender, EventArgs e) {
        IModelListViewExtender modelListView = View.Model as IModelListViewExtender;
        if(modelListView != null && modelListView.IsGroupFooterVisible) {
            GridListEditor gridListEditor = View.Editor as GridListEditor;
            if(gridListEditor != null) {
                GridView gridView = gridListEditor.GridView;
                for(int i = 0; i < gridView.GroupSummary.Count; i++) {
                    IModelColumnExtender modelColumn = View.Model.Columns[
                        gridView.GroupSummary[i].FieldName] as IModelColumnExtender;
                    if(modelColumn != null) {
                        modelColumn.GroupFooterSummaryType = gridView.GroupSummary[i].SummaryType;
                    }
                }
            }
        }    
    }
    protected override void OnViewControlsCreated() {
        base.OnViewControlsCreated();
        IModelListViewExtender modelListView = View.Model as IModelListViewExtender;
        if(modelListView != null && modelListView.IsGroupFooterVisible) {
            GridListEditor gridListEditor = View.Editor as GridListEditor;
            if(gridListEditor != null) {
                GridView gridView = gridListEditor.GridView;
                gridView.OptionsView.GroupFooterShowMode = GroupFooterShowMode.VisibleAlways;
                foreach(IModelColumn modelColumn in View.Model.Columns) {
                    IModelColumnExtender modelColumnExtender = modelColumn as IModelColumnExtender;
                    if(modelColumnExtender != null && 
                        modelColumnExtender.GroupFooterSummaryType != SummaryItemType.None) {
                            GridColumn gridColumn = gridView.Columns[
                                modelColumn.ModelMember.MemberInfo.BindingName];
                            gridView.GroupSummary.Add(modelColumnExtender.GroupFooterSummaryType, 
                                modelColumn.Id, gridColumn);
                    }
                }
            }
        }
    }
    protected override void OnActivated() {
        base.OnActivated();
        View.ModelSaved += View_ModelSaved;
    }
    protected override void OnDeactivated() {
        View.ModelSaved -= View_ModelSaved;
        base.OnDeactivated();
    }
}

ASP.NET Web Forms-Specific Steps

Inherit a WebGroupFooterViewController from the ViewController<ListView> type in the ASP. NET Web Forms Module. This base class choice ensures that this Controller activates in List Views only.

Override the protected OnViewControlsCreated method. If the IsGroupFooterVisible property is set to true for the current List View, display the group footer.

Users cannot make changes to column summary settings in ASP.NET Web Forms UI. You do not need to handle the ModelSaved event.

using System;
using DevExpress.Data;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using DevExpress.ExpressApp.Web.Editors.ASPx;
using DevExpress.Web;
//...
public class WebGroupFooterViewController : ViewController<ListView> {
    protected override void OnViewControlsCreated() {
        base.OnViewControlsCreated();
        IModelListViewExtender modelListView = View.Model as IModelListViewExtender;
        if(modelListView != null && modelListView.IsGroupFooterVisible) {
            ASPxGridListEditor gridListEditor = View.Editor as ASPxGridListEditor;
            if(gridListEditor != null) {
                ASPxGridView gridView = gridListEditor.Grid;
                gridView.Settings.ShowGroupFooter = GridViewGroupFooterMode.VisibleAlways;
                foreach(IModelColumn modelColumn in View.Model.Columns) {
                    IModelColumnExtender modelColumnExtender = modelColumn as IModelColumnExtender;
                    if(modelColumnExtender != null && 
                        modelColumnExtender.GroupFooterSummaryType != SummaryItemType.None) {
                        string fieldName = modelColumn.ModelMember.MemberInfo.BindingName.ToUpper();
                        ASPxSummaryItem summaryItem = null;
                        foreach(ASPxSummaryItem currentItem in gridView.GroupSummary) {
                            if(currentItem.FieldName.ToUpper() == fieldName) {
                                currentItem.ShowInGroupFooterColumn = modelColumn.Caption;
                                summaryItem = currentItem;
                                break;
                            }
                        }
                        if(summaryItem == null) {
                            summaryItem = new ASPxSummaryItem(fieldName, modelColumnExtender.GroupFooterSummaryType);
                            summaryItem.ShowInGroupFooterColumn = modelColumn.Caption.ToUpper();
                            gridView.GroupSummary.Add(summaryItem);
                        }
                    }
                }
            }
        }
    }
}

ASP.NET Core Blazor-Specific Steps

Inherit a WebGroupFooterViewController from the ViewController<ListView> type in the ASP.NET Core Blazor Module. This base class choice ensures that the controller activates in List Views only.

Override the protected OnViewControlsCreated method. If the IsGroupFooterVisible property is set to true for the current List View, display the group footer.

Users cannot customize summary settings in ASP.NET Core Blazor UI. You do not need to handle the ModelSaved event.

using DevExpress.Data;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor.Editors;
using DevExpress.ExpressApp.Model;
//...
public class BlazorGroupFooterViewController : ViewController<ListView> {
    protected override void OnViewControlsCreated() {
        base.OnViewControlsCreated();
        if (View.Model is IModelListViewExtender modelListView && modelListView.IsGroupFooterVisible && View.Editor is DxGridListEditor gridListEditor) {
            gridListEditor.GridModel.GroupFooterDisplayMode = DevExpress.Blazor.GridGroupFooterDisplayMode.Always;
            if (gridListEditor.GetGridAdapter() is IDxGridSummaryItemsOwner summaryItemsOwner) {
                foreach (var modelColumn in View.Model.Columns) {
                    if (modelColumn is IModelColumnExtender modelColumnExtender && modelColumnExtender.GroupFooterSummaryType != SummaryItemType.None) {
                        var summaryItem = (DxGridSummaryItemWrapper)summaryItemsOwner.CreateItem(modelColumn.Id, modelColumnExtender.GroupFooterSummaryType);
                        summaryItem.SummaryItemModel.FooterColumnName = modelColumn.Id;
                        summaryItemsOwner.GroupSummary.Add(summaryItem);
                    }
                }
            }
        }
    }
}

Run the Application

Rebuild your solution. Invoke the Model Editor for the base Module and navigate to a ListView node. Change the following settings:

  • Set the IsGroupPanelVisible property to true to allow users to group data.
  • Set the new IsGroupFooterVisible property to true to enable group footers.
  • Specify summary types for Column nodes. Use the new GroupFooterSummaryType property.

Run the application. Open a List View with a group panel and group the List View by a column. You can see the footer with the specified summary types.

Extend the app model

See Also