Two mechanisms control which objects a listing page displays – query modifiers, which restrict the data the page retrieves, and filters, which allow users to narrow the listing down according to their own criteria.
You can modify the query that retrieves objects for display in the grid via PageConfiguration.QueryModifiers and the AddModifier method. The query uses the system's ObjectQuery API to retrieve the table data. See ObjectQuery API to learn more about the feature and available parameterization options.
Modifiers can be useful if you wish to, for example, filter listed objects based on other parameters present in the URL. See the Page URLs and routing section on UI pages for more information about routing, the page URL hierarchy, and passing parameters via page URLs.
// Binds a site ID parameter provided by a parent page in the hierarchy
[PageParameter(typeof(IntPageModelBinder))]
public int SiteId { get; set; }
// ...
public override Task ConfigurePage()
{
PageConfiguration.QueryModifiers
.AddModifier((query, _) =>
{
// Filters displayed objects by the 'SiteID' parameter
return query.WhereEquals(nameof(SiteDomainAliasInfo.SiteID), SiteId);
});
return base.ConfigurePage();
}Listing pages often contain a large number of objects. Filters allow users to limit which objects are displayed according to specified criteria.
You can implement filters for both your own custom listing pages and the default listing pages in the Xperience administration UI.
Add a model class to your custom admin project with properties representing individual inputs in the filter.
Define the filter UI by assigning Editing components to the properties (like when preparing model-based edit pages).
Decorate the filter properties with the FilterCondition attribute (available in the Kentico.Xperience.Admin.Base.Filters namespace). The attribute has the following parameters:
BuilderType – a type implementing IWhereConditionBuilder, which generates the where condition applied to the listing for the given property. See Create filter condition builders below for more information.
ColumnName – the column name passed to the IWhereConditionBuilder implementation assigned to the property. Specify a column of the object type displayed in the listing, e.g., using the nameof (opens in a new tab) expression.
Both attribute parameters are optional.
If you omit BuilderType, a basic equality condition builder is used. The condition is fulfilled if the specified column is equal to the filter property's value.
If ColumnName is omitted, the name of the property in the model class is used as the column name.
Properties without the FilterCondition attribute automatically generate a basic equality condition (same behavior as when using the attribute with both parameters omitted).
(Optional) You can also decorate properties in the filter model class with the following attributes:
FilterLabel – sets the text of the property's "filter summary chip", which appears in the Applied filters section above the listing. If not added, the filter summary text falls back to the Label of the property's assigned editing component, or the name of the property itself if required. Intended for properties decorated with the FilterCondition attribute.FilterIgnore – ensures that the property's value does not affect the resulting filter condition. Intended for properties that are not decorated with the FilterCondition attribute. For example, if you wish to display a property that modifies the filter form using visibility conditions, but does not affect the filtering itself.When the filter is applied, the conditions are generated for all properties in the model class and combined using the SQL AND operator. The resulting listing displays only items that fulfill all of the conditions.
using System.Collections.Generic;
using CMS.Membership;
using Kentico.Xperience.Admin.Base.Filters;
using Kentico.Xperience.Admin.Base.FormAnnotations;
using Kentico.Xperience.Admin.Base.Forms;
public class UserListFilterModel
{
// Text input that filters listed users based on their email address
[TextInputComponent(Label = "User email", Order = 0)]
[FilterCondition(BuilderType = typeof(ContainsTextConditionBuilder), ColumnName = nameof(UserInfo.Email))]
[FilterLabel("Email")]
public string UserEmail { get; set; }
// Drop-down selector that filters the listing to show only active or inactive user accounts
[DropDownComponent(
Label = "User status",
Placeholder = "Any",
Options = "true;Active\r\nfalse;Inactive",
Order = 1)]
[FilterCondition(BuilderType = typeof(IsTrueConditionBuilder), ColumnName = nameof(UserInfo.UserEnabled))]
[FilterLabel("Status")]
public string UserEnabled { get; set; }
}To define filtering conditions, prepare classes that implement IWhereConditionBuilder (available in the Kentico.Xperience.Admin.Base.Filters namespace). Define the Build method and return an IWhereCondition object (available in the CMS.DataEngine namespace).
Recommendations for implementing the Build method:
WhereCondition class (except when throwing exceptions for invalid error states). If you do not wish to affect the filtering condition, return a new (empty) WhereCondition object rather than null.value parameter is passed as an object, so perform appropriate type-testing and casting operations.WhereStartsWith condition provides better performance than WhereContains.value parameter to directly pass SQL query text to the where condition.using System;
using System.Threading.Tasks;
using CMS.DataEngine;
using Kentico.Xperience.Admin.Base.Filters;
public class ContainsTextConditionBuilder : IWhereConditionBuilder
{
public Task<IWhereCondition> Build(string columnName, object value)
{
if (string.IsNullOrEmpty(columnName))
{
throw new ArgumentException($"{nameof(columnName)} cannot be a null or an empty string.");
}
// Creates a new where condition
var whereCondition = new WhereCondition();
if (value is null || value is not string )
{
// Returns an empty condition if a valid value is not specified
return Task.FromResult<IWhereCondition>(whereCondition);
}
// Adds a where condition returning only items that contain the value in the specified column
whereCondition.WhereContains(columnName, (string)value);
return Task.FromResult<IWhereCondition>(whereCondition);
}
}using System;
using System.Threading.Tasks;
using CMS.DataEngine;
using Kentico.Xperience.Admin.Base.Filters;
public class IsTrueConditionBuilder : IWhereConditionBuilder
{
public Task<IWhereCondition> Build(string columnName, object value)
{
if (string.IsNullOrEmpty(columnName))
{
throw new ArgumentException($"{nameof(columnName)} cannot be a null or an empty string.");
}
// Creates a new where condition
var whereCondition = new WhereCondition();
if (value is null || value is not string userEnabled)
{
// Returns an empty condition if a valid filtering option is not selected
return Task.FromResult<IWhereCondition>(whereCondition);
}
if (userEnabled.Equals("true", StringComparison.InvariantCultureIgnoreCase))
{
// Adds a where condition returning only enabled user accounts
whereCondition.WhereTrue(columnName);
}
if (userEnabled.Equals("false", StringComparison.InvariantCultureIgnoreCase))
{
// Adds a where condition returning only users that are not enabled
whereCondition.WhereFalse(columnName);
}
return Task.FromResult<IWhereCondition>(whereCondition);
}
}To add a filter to your own custom listing pages, assign an instance of your filter model class to the UI page's PageConfiguration.FilterFormModel property.
public override Task ConfigurePage()
{
// ...
// Assigns a listing filter model
PageConfiguration.FilterFormModel = new UserListFilterModel();
return base.ConfigurePage();
}If you wish to add a filter to an existing listing page in the Xperience administration, set the FilterFormModel property through a UI page extender.
[assembly: PageExtender(typeof(UserListExtender))]
public class UserListExtender : PageExtender<UserList>
{
// Configures the listing template on which UserList is based
public override Task ConfigurePage()
{
var configuration = Page.PageConfiguration;
// Assigns a listing filter model
configuration.FilterFormModel = new UserListFilterModel();
return base.ConfigurePage();
}
}