Skip to main content
A newer version of this page is available. .
.NET Framework 4.5.2+

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

  • 8 minutes to read

To demonstrate how to extend the Application Model, this topic details how to display a Group Footer for List Views. An IsGroupFooterVisible property will be added to the to the Views | <ListView> node. When set to true for a ListView, a special Controller will enable the group footer. To specify a summary type for different columns, a GroupFooterSummaryType property will be added to the ListView | Columns | Column node. For general information on extending the Application Model, refer to the Extend and Customize the Application Model in Code help topic.

Tip

A complete sample project is available in the DevExpress Code Examples database at https://supportcenter.devexpress.com/ticket/details/e213/how-to-extend-the-application-model.

  • Implement the interfaces exposing 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>();
        }
    }
    
  • Create a WinGroupFooterViewController ViewController in the Windows Forms Module. Inherit it from the ViewController<ListView> type, since this Controller must be activated in List Views only.

  • Override the protected OnViewControlsCreated method to display the group footer, if the IsGroupFooterVisible property is set to true for the current List View. Additionally, when the Controller is activated, handle the View.ModelSaved event to save the group footer summary type for different columns into Application Model, when the current List View is closing.

    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();
        }
    }
    
  • Create a WebGroupFooterViewController ViewController in the ASP.NET Web Forms Module. Inherit it from the ViewController<ListView> type, since this Controller must be activated in List Views only.

  • Override the protected OnViewControlsCreated method to display the group footer, if the IsGroupFooterVisible property is set to true for the current List View. There is no need to handle the ModelSaved event since end-users cannot customize summary types for different columns in the ASP.NET Web Forms UI.

    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);
                            }
                        }
                    }
                }
            }
        }
    }
    
  • Create a BlazorGroupFooterViewController ViewController in the ASP.NET Core Blazor Module. Inherit it from the ViewController<ListView> type, since this Controller must be activated in List Views only.

  • Override the protected OnViewControlsCreated method to display the group footer, if the IsGroupFooterVisible property is set to true for the current List View. There is no need to handle the ModelSaved event since end-users cannot customize summary types for different columns in the ASP.NET Core Blazor UI.

    using DevExpress.ExpressApp;
    using DevExpress.ExpressApp.Blazor.Editors.Grid;
    using MainDemo.Module.BusinessObjects;
    // ...
    public class BlazorGroupFooterViewController : ViewController<ListView> {
        protected override void OnViewControlsCreated() {
            base.OnViewControlsCreated();
            if (View.Model is IModelListViewExtender modelListView) {
                if (modelListView.IsGroupFooterVisible && View.Editor is GridListEditor gridListEditor) {
                    IDxDataGridAdapter dataGridAdapter = gridListEditor.GetDataGridAdapter();
                    dataGridAdapter.DataGridModel.GroupSummary = DataGridGroupFooterSummary.Create(View.Model.Columns);
                }
            }
        }
    }
    
  • Create a DataGridGroupFooterSummary Razor component in the ASP.NET Core Blazor Module and set its Build Action property to Content.

    @using DevExpress.Blazor
    @using DevExpress.ExpressApp.Model
    @using MainDemo.Module.BusinessObjects
    
    @foreach (IModelColumn modelColumn in ModelColumns) {
        if (modelColumn is IModelColumnExtender modelColumnExtender) {
            if (modelColumnExtender.GroupFooterSummaryType != DevExpress.Data.SummaryItemType.None) {
                <DxDataGridSummaryItem Field=@modelColumn.ModelMember.MemberInfo.BindingName
                                    SummaryType=ConvertSummaryItemType(modelColumnExtender.GroupFooterSummaryType)
                                    GroupSummaryPosition=GroupSummaryPosition.GroupFooter />
            }
        }
    }
    
    @code {
        [Parameter] 
        public IModelColumns ModelColumns { get; set; }
        public static RenderFragment Create(IModelColumns modelColumns) {
            return@<DataGridGroupFooterSummary ModelColumns=modelColumns />;
        }
        private SummaryItemType ConvertSummaryItemType(DevExpress.Data.SummaryItemType summaryItemType) {
            return summaryItemType switch {
                DevExpress.Data.SummaryItemType.Sum => SummaryItemType.Sum,
                DevExpress.Data.SummaryItemType.Average => SummaryItemType.Avg,
                DevExpress.Data.SummaryItemType.Count => SummaryItemType.Count,
                DevExpress.Data.SummaryItemType.Custom => throw new NotSupportedException(),
                DevExpress.Data.SummaryItemType.Max => SummaryItemType.Max,
                DevExpress.Data.SummaryItemType.Min => SummaryItemType.Min,
                DevExpress.Data.SummaryItemType.None => SummaryItemType.None,
                _ => SummaryItemType.None
            };
        }
    }
    
  • Rebuild you solution and invoke the Model Editor for the base Module. Set a ListView node’s IsGroupPanelVisible property to true to be able to group the List View’s columns. Set the newly added IsGroupFooterVisible property to true. Specify summary types for the ListView node’s Column nodes.

  • Run the application. Display the List View with a group panel and group the List View by a column. The footer with the specified summary types will be displayed.
See Also