help.axcms.netAxinom Logo
Save Save Chapter Send Feedback

Adding a Filter to Article Overview

 

Filtering and Sorting Overview

Each overview page in AxCMS offers a search filter. It's located in the upper left area of the page. The search filter has 2 modes: basic and extended. Basic search is a simple keyword search – the system looks for keyword occurrences in different fields of the object. Advanced search allows defining the exact field where the keyword should be searched, and filtering objects by certain parameter values.

Filter Control

First, let's bind an ArticleFilter control to the overview page:

01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
<%@ Page language="c#" Codebehind="ArticleOverview.aspx.cs" 
AutoEventWireup="false" Inherits="Extras.ArticleOverview" %>
<%@ Register TagPrefix="AxMP" namespace="Axinom.AECMS.Backend" 
assembly="Axinom.AECMS.Backend" %>
<%@ Register TagPrefix="AxCMS" TagName="Filter" 
Src="ArticleFilter.ascx" %>
<%@ Register TagPrefix="AxCMS" TagName="BaseGridTemplate" 
Src="../admin/templates/BaseGridTemplate.ascx" %>

<AxMP:ContentContainer runat="server" ID="ctlContentContainer" >
    <AxMP:Content id="Filter" runat="server">
        <AxCMS:Filter runat="server" ID="_filter"/>
    </AxMP:Content>
    <AxMP:Content id="List" runat="server">
        <AxCMS:BaseGridTemplate runat="server" ID="_grid"/>
    </AxMP:Content>
</AxMP:ContentContainer>

The filter variable is already defined in GridOverviewCMSPage and refers to the BaseFilter type. Our Filter class should also extend the BaseFilter class. Let’s add the following line of code to ArticleOverview.aspx.cs:

_filter.IsExpert = true;

This property defines if extended search should be available at all. Just set _filter.IsExpert to false if you don’t want to implement the extended search.

The ASCX part of the ArticleFilter consists of two panels: _generalPanel and expert_Panel. The first panel is for basic and the second for extended search. The _generalPanel can stay as it is; it always has only one textbox (_searchTermTextBox). To expertPanel we should add some new textboxes like Name, Price and Description. When you’ve added these textboxes, the expertPanel will look something like this:

01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
<Ax:AxinomPanel id="filterexpertPanel" runat="server" Headline="Filter" width="100%" CssClass="keyarea">
  <table class="FilterTable">
    <tr>
      <td colspan="2">
      <b>
        <asp:Literal runat="server" ID="Literal2">Erweiterte Suche</asp:Literal>
      </b>&#160; 
      <asp:LinkButton runat="server" id="_generalFilterButton" Text="einfach"></asp:LinkButton></td>
    </tr>
    <tr>
      <td>Name:</td>
      <td>
        <asp:TextBox runat="server" id="nameTextBox" MaxLength="255" Width="100%" />
      </td>
    </tr>
    <tr>
      <td>Beschreibung:</td>
      <td>
        <asp:TextBox runat="server" id="descriptionTextBox" MaxLength="255" Width="100%" />
      </td>
    </tr>
    <tr>
      <td>Max. Preis:</td>
      <td>
        <asp:TextBox runat="server" id="maxPriceTextBox" MaxLength="20" Width="100%" />
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <asp:Button runat="server" id="_applyExpertFilterButton" Text="Suchen" CssClass="button" Width="83" />
        <asp:Button runat="server" id="_removeExpertFilterButton" Text="Zuruck" CssClass="button" Width="100" />
      </td>
    </tr>
  </table>
</Ax:AxinomPanel>

FilterParameters

When you open the ArticleFilter code-behind file, you will see that it works almost with one instance of FilterParameters. One of the FilterParameters extended classes encapsulates all the filter parameters. These will be filled by the GUI and then forwarded to the business logic. Thus it is possible to add new properties to the filter without changing any of the signatures in the code. The base class has only one searchTerm property.

We need to extend our own ArticleFilterParameters class, which is on the BL (business logic) level. All FilterParameters classes must have a [Serializable] attribute, otherwise this class is not a container for the properties anymore.

The ArticleFilter code-behind file has only 3 methods:

  • CreateFilterParameters is a factory method. It creates and returns only one instance of our ArticleFilterParameters class.
  • DataBind becomes an instance of FilterParameters and binds particular properties to the GUI controls. Although the parameter filterParam is defined to have a base type FilterParameters, at runtime it gets instances of more specific types inherited from FilterParameters. This gives you a possibility to cast to this more specific type safely.
  • ReadFilterParameters takes the values form the control and puts them into the instance of FilterParameters class.

So the ArticleFilter class would look like this:

01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
 public class ArticleFilter : BaseFilter
    {
        protected TextBox nameTextBox;
        protected TextBox descriptionTextBox;
        protected TextBox maxPriceTextBox;
        
        public override FilterParameters CreateFilterParameters()
        {
            return new ArticleFilterParameters();
        }
        
        public override void DataBind(FilterParameters filterParams)
        {
            base.DataBind(filterParams);

            _searchTermTextBox.Text = filterParams.SearchTerm;

            ArticleFilterParameters filterParameters = filterParams 
as ArticleFilterParameters;
            if (filterParameters != null)
            {
                nameTextBox.Text = filterParameters.Name;
                descriptionTextBox.Text = filterParameters.Description;
                maxPriceTextBox.Text = filterParameters.MaxPrice.ToString();
            }
        }


        public override FilterParameters ReadFilterParameters()
        {
            ArticleFilterParameters filterParameters = (ArticleFilterParameters) 
CreateFilterParameters();
            filterParameters.FilterMode = this.Mode;
            if(this.Mode == FilterMode.General)
            {
                filterParameters.SearchTerm = _searchTermTextBox.Text.Trim();
            }
            else
            {
                filterParameters.Name = nameTextBox.Text.Trim();
                filterParameters.Description = descriptionTextBox.Text.Trim();
                if (string.IsNullOrEmpty(maxPriceTextBox.Text.Trim()))
                {
                    filterParameters.MaxPrice = null;
                }
                else
                {
                    filterParameters.MaxPrice = System.Convert.ToDecimal
(maxPriceTextBox.Text.Trim());
                }
            }
            return filterParameters;
        }
    }

 Overview Page

So far, we have looked at how to implement a filter, but not how it actually works. This procedure consists of the following events:

  1. User chooses the filter mode (basic/extended).
  2. User types a search keyword in the input field and clicks Search.
  3. Filter control gets the input from the control and creates the FilterParameters object.
  4. Filter control executes filter event and gives FilterParameters as the parameter.
  5. The overview page catches this event and calls the GetDataSource method. This method takes FilterParameters as the parameter. So the actual task for this method is to get the data that matches the filter criteria.

Until now, GetDataSource has ignored the filter completely. Let’s change that.

As a precaution, we will create a default filter, which will be used if no filter is defined.  CreateDefaultFilterParameters is easy to implement:





protected override FilterParameters CreateDefaultFilterParameters()
        {
            return _filter.CreateFilterParameters();
        }

The data was loaded with the LoadAll method of adapter in GetDataSource method of ArticleOverviewHelper.

Now we can modify this query before LoadAll execution. Let’s use filter properties for the query. This task will be delegated to the filter itself (ArticleFilterParameters class).

 public override void ApplyToQuery(DbSelectQuery query, int skipFirst, string sort)

The ApplyToQuery method can also take over the transformation of the sort string. So we'll have just:







AxDbAdapter adapter = new AxDbAdapter(typeof(Article));
DbSelectQuery query = adapter.GetDefaultSelectQuery();
filter.ApplyToQuery(query, 0, sort);
ArrayList al = adapter.LoadAll(query);
this.VirtualItemCount = al.Count;
return al;

And in ApplyToQuery in ArticleFilterParameters class we will have this:

01 
02 
03 
04 
05 
06 
07 
08 
09 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
         if(this.FilterMode == FilterMode.General)
            {
                query.AddWhere("[Name] LIKE @SearchTerm 
OR [Description] LIKE @SearchTerm");
                query.AddParameter("@SearchTerm", "%" 
+ this.SearchTerm + "%");
            }
            else
            {
                if(!string.IsNullOrEmpty(this.Name))
                {
                    query.AddWhere("[Name] LIKE @Name");
                    query.AddParameter("@Name", "%" 
+ this.Name + "%");
                }
                if (!string.IsNullOrEmpty(this.Description))
                {
                    query.AddWhere("[Description] LIKE @Description");
                    query.AddParameter("@Description", "%" 
+ this.Description + "%");
                }
                if (this.MaxPrice!=null)
                {
                    query.AddWhere("[Price] <= @MaxPrice");
                    query.AddParameter("@MaxPrice", this.MaxPrice);
                }
            }

When the search filter has been implemented, the article overview page will have this Filter box:


Next article: Adding Custom Sorting to Article Overview