Example E1554
Visible to All Users

XAF - How to show a filter dialog before a List View

This example displays a pop-up filter dialog that allows users to set a filter for a list view before the application starts to load list view data. Users can create filters and save them in a data source. This approach can be useful when the list view contains a large amount of data.

Filter for ListView

Implementation Details

  1. Extend the Application Model with an additional property.
    • Implement an interface that exposes the AdditionalCriteria property. This property stores the applied filter criteria.
    • Override the ExtendModelInterfaces method of your base Module to extend the Application Model with the declared interface and the AdditionalCriteria property.
  2. Create the ViewFilterObject class. Instances of this class store user filters.
  3. Create the non-persistent ViewFilterContainer class. An object of this class contains a list of user filters (ViewFilterObject objects) and the currently applied filter. The ViewFilterContainer's Detail View serves as the filter dialog.
  4. Implement ShowFilterDialogController to display the filter dialog. When a user selects a filter and clicks the OK button, the controller assigns the corresponding filter criteria to the AdditionalCriteria Application Model property.
  5. Implement NewViewFilterObjectController to initialize a new instance of the ViewFilterObject class when a user clicks New in the ViewFilterObject lookup List View.

Files to Review

Documentation

More Examples

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

EFCore/DialogBeforeListViewEF/DialogBeforeListViewEF.Module/Module.cs
C#
using System.ComponentModel; using DevExpress.ExpressApp; using DevExpress.ExpressApp.DC; using DevExpress.Persistent.Base; using DevExpress.ExpressApp.Model; using DevExpress.ExpressApp.Actions; using DevExpress.ExpressApp.Editors; using DevExpress.ExpressApp.Updating; using DevExpress.ExpressApp.Model.Core; using DevExpress.ExpressApp.Model.DomainLogics; using DevExpress.ExpressApp.Model.NodeGenerators; namespace DialogBeforeListViewEF.Module; // For more typical usage scenarios, be sure to check out https://docs.devexpress.com/eXpressAppFramework/DevExpress.ExpressApp.ModuleBase. public sealed class DialogBeforeListViewEFModule : ModuleBase { public DialogBeforeListViewEFModule() { // // DialogBeforeListViewEFModule // RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.SystemModule.SystemModule)); RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Objects.BusinessClassLibraryCustomizationModule)); } public override IEnumerable<ModuleUpdater> GetModuleUpdaters(IObjectSpace objectSpace, Version versionFromDB) { ModuleUpdater updater = new DatabaseUpdate.Updater(objectSpace, versionFromDB); return new ModuleUpdater[] { updater }; } public override void Setup(XafApplication application) { base.Setup(application); // Manage various aspects of the application UI and behavior at the module level. } public override void ExtendModelInterfaces(ModelInterfaceExtenders extenders) { base.ExtendModelInterfaces(extenders); extenders.Add<IModelListView, IModelListViewAdditionalCriteria>(); } } public interface IModelListViewAdditionalCriteria : IModelNode { [DefaultValue("")] string AdditionalCriteria { get; set; } }
EFCore/DialogBeforeListViewEF/DialogBeforeListViewEF.Module/BusinessObjects/ViewFilterObject.cs
C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.DC; using DevExpress.ExpressApp.Editors; using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl.EF; using System.ComponentModel; using System.ComponentModel.DataAnnotations.Schema; namespace E1554.Module { [DefaultProperty(nameof(FilterName))] public class ViewFilterObject : BaseObject { public virtual string FilterName { get; set; } [Browsable(false)] public virtual string DataTypeName { get { return fDataType == null ? string.Empty : fDataType.FullName; } set { ITypeInfo typeInfo = XafTypesInfo.Instance.FindTypeInfo(value); fDataType = typeInfo == null ? null : typeInfo.Type; } } private Type fDataType; [NotMapped, ImmediatePostData] [Browsable(false)] public Type DataType { get { return fDataType; } set { if(fDataType == value) return; fDataType = value; Criteria = string.Empty; } } [CriteriaOptions(nameof(DataType))] [FieldSize(FieldSizeAttribute.Unlimited)] [EditorAlias(EditorAliases.CriteriaPropertyEditor)] public virtual string Criteria { get; set; } } }
EFCore/DialogBeforeListViewEF/DialogBeforeListViewEF.Module/BusinessObjects/ViewFilterContainer.cs
C#
using DevExpress.Data.Filtering; using DevExpress.ExpressApp; using DevExpress.ExpressApp.DC; using DevExpress.ExpressApp.Editors; using DevExpress.Persistent.Base; using System.ComponentModel; namespace E1554.Module { [DomainComponent] public class ViewFilterContainer : NonPersistentBaseObject, IObjectSpaceLink { private ViewFilterObject filter; [DataSourceProperty(nameof(Filters))] [ImmediatePostData] public ViewFilterObject Filter { get { return filter; } set { filter = value; } } private IList<ViewFilterObject> filters; [Browsable(false)] public IList<ViewFilterObject> Filters { get { if(filters == null && ObjectType != null) { filters = objectSpace.GetObjects<ViewFilterObject>(CriteriaOperator.FromLambda<ViewFilterObject>(v => v.DataTypeName == ObjectType.FullName)); } return filters; } } [CriteriaOptions(nameof(ObjectType))] [Browsable(false)] public string Criteria { get { return Filter != null ? Filter.Criteria : String.Empty; } set { if(Filter != null) { Filter.Criteria = value; } } } private Type objectType; [Browsable(false)] public Type ObjectType { get { return objectType; } set { objectType = value; } } private IObjectSpace objectSpace; IObjectSpace IObjectSpaceLink.ObjectSpace { get { return objectSpace; } set { objectSpace = value; } } } }
EFCore/DialogBeforeListViewEF/DialogBeforeListViewEF.Module/Controllers/ShowFilterDialogController.cs
C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.Actions; using DevExpress.ExpressApp.Editors; using DevExpress.Persistent.Base; using DialogBeforeListViewEF.Module; namespace E1554.Module { public class ShowFilterDialogController : ViewController<ListView> { const string DisableReason = "SuitableView"; SimpleAction showFilterDialogAction; public ShowFilterDialogController() { TargetViewNesting = Nesting.Root; showFilterDialogAction = new SimpleAction(this, "ShowFilterDialog", PredefinedCategory.Filters); showFilterDialogAction.Execute += ShowFilterDialogAction_Execute; } protected override void OnActivated() { base.OnActivated(); if(Frame.Context == TemplateContext.ApplicationWindow || Frame.Context == TemplateContext.View) { showFilterDialogAction.Active[DisableReason] = true; View.CollectionSource.Criteria[nameof(ShowFilterDialogController)] = CollectionSourceBase.EmptyCollectionCriteria; ShowFilterDialogOnActivated(); } else { showFilterDialogAction.Active[DisableReason] = false; } } protected virtual void ShowFilterDialogOnActivated() { ShowFilterDialog(); } private void ShowFilterDialogAction_Execute(object sender, SimpleActionExecuteEventArgs e) { ShowFilterDialog(); } protected void ShowFilterDialog() { NonPersistentObjectSpace nonPersistentObjectSpace = (NonPersistentObjectSpace)Application.CreateObjectSpace<ViewFilterContainer>(); IObjectSpace persistentObjectSpace = Application.CreateObjectSpace<ViewFilterObject>(); nonPersistentObjectSpace.AdditionalObjectSpaces.Add(persistentObjectSpace); ViewFilterContainer newViewFilterContainer = nonPersistentObjectSpace.CreateObject<ViewFilterContainer>(); newViewFilterContainer.ObjectType = View.ObjectTypeInfo.Type; newViewFilterContainer.Filter = GetFilterObject(persistentObjectSpace, ((IModelListViewAdditionalCriteria)View.Model).AdditionalCriteria, newViewFilterContainer.ObjectType); DetailView filterDetailView = Application.CreateDetailView(nonPersistentObjectSpace, newViewFilterContainer); filterDetailView.Caption = string.Format("Filter for the {0} ListView", View.Caption); Application.ShowViewStrategy.ShowViewInPopupWindow(filterDetailView, () => FilterDetailView_OK(filterDetailView)); } private void FilterDetailView_OK(DetailView filterDetailView) { filterDetailView.ObjectSpace.CommitChanges(); ViewFilterContainer currentViewFilterContainer = (ViewFilterContainer)filterDetailView.CurrentObject; ((IModelListViewAdditionalCriteria)View.Model).AdditionalCriteria = currentViewFilterContainer.Criteria; View.CollectionSource.Criteria[nameof(ShowFilterDialogController)] = CriteriaEditorHelper.GetCriteriaOperator(currentViewFilterContainer.Criteria, currentViewFilterContainer.ObjectType, ObjectSpace); } private ViewFilterObject GetFilterObject(IObjectSpace objectSpace, string listViewCriteria, Type objectType) { ViewFilterObject filterObject = objectSpace.FirstOrDefault<ViewFilterObject>(fo => fo.Criteria == listViewCriteria && fo.DataTypeName == objectType.FullName); if(filterObject == null) { filterObject = objectSpace.FirstOrDefault<ViewFilterObject>(fo => fo.FilterName == "All" && fo.DataTypeName == objectType.FullName); if(filterObject == null) { ViewFilterObject newFilterObject = objectSpace.CreateObject<ViewFilterObject>(); newFilterObject.DataType = objectType; newFilterObject.FilterName = "All"; objectSpace.CommitChanges(); filterObject = objectSpace.GetObject(newFilterObject); } filterObject.DataType = objectType; filterObject.Criteria = listViewCriteria; } return filterObject; } } }
EFCore/DialogBeforeListViewEF/DialogBeforeListViewEF.Module/Controllers/NewViewFilterObjectController.cs
C#
using DevExpress.ExpressApp; using DevExpress.ExpressApp.SystemModule; namespace E1554.Module { public class NewViewFilterObjectController : ObjectViewController<ListView, ViewFilterObject> { public NewViewFilterObjectController() { TargetViewId = "ViewFilterObject_LookupListView"; } protected override void OnActivated() { base.OnActivated(); if(View.CollectionSource is PropertyCollectionSource && ((PropertyCollectionSource)View.CollectionSource).MasterObjectType == typeof(ViewFilterContainer)) { NewObjectViewController newObjectViewController = Frame.GetController<NewObjectViewController>(); if(newObjectViewController != null) { newObjectViewController.ObjectCreated += new EventHandler<ObjectCreatedEventArgs>(ViewController1_ObjectCreated); } } } void ViewController1_ObjectCreated(object sender, ObjectCreatedEventArgs e) { if(e.CreatedObject is ViewFilterObject) { ViewFilterObject newViewFilterObject = (ViewFilterObject)e.CreatedObject; PropertyCollectionSource pcs = (PropertyCollectionSource)View.CollectionSource; newViewFilterObject.DataType = ((ViewFilterContainer)pcs.MasterObject).ObjectType; } } protected override void OnDeactivated() { base.OnDeactivated(); if(View.CollectionSource is PropertyCollectionSource && ((PropertyCollectionSource)View.CollectionSource).MasterObjectType == typeof(ViewFilterContainer)) { NewObjectViewController newObjectViewController = Frame.GetController<NewObjectViewController>(); if(newObjectViewController != null) { newObjectViewController.ObjectCreated -= new EventHandler<ObjectCreatedEventArgs>(ViewController1_ObjectCreated); } } } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.