Dynamic filters outside of the grid

4 posts, 1 answers
  1. Datamex
    Datamex avatar
    161 posts
    Member since:
    Jun 2012

    Posted 11 Aug 2009 Link to this post

    For a project I'm working on, we're looking for a way to dynamically add filters to a page which then control the dataoutput in a RadGrid. We want to add the filters dynamically because we want the customer to be able to change which properties can be filtered and what filtertype (textbox, dropdown, colourpicker, etc.) should be used.

    The filter should work as follows:

    • The customer links a filter to a certain property and specifies the filtertype (for this example: dropdown). This is specified in a database table.

    • A user control which contains all the filter loads all filters specified, this is done dynamically according to the database table
    • The filters load all values of the specified property as options. The first time the page loads; this would be the (disctinct) values of all items. 
    • Now the user selects a value from one of the filters; the page reloads 
    • Only items which have the specified filter value are retrieved, the user may specify one or more filters at the same time. 
    • Once a user drills down by filtering, only filtervalues of the retrieved items should be used in the other filters to hide values which aren't present in the resulting list of items; so all other filters have to be rebound according to the new query.

     

    I have the following problems:

    • When I create the filters runtime, events are lost because the controls get recreated each postback. 

    • I could place the filters in PreInit which should solve this, but then determining which controls should be loaded becomes a problem since loading all environment vars isn't finished yet?
    • I don't know a good way of returning all the filter values to a central point from which I can make a good query. 
    • The query has to be dynamic. I'm using linq which I want to make dynamic so I don't have to select everything everytime. How to make a dynamic select query based on a string stored in the database? 
    • I have to select items based on the filtervalues and then adjust the rest of the filters to the already made selection. That kind of messes up the whole regular databinding sequence.

    Any help in one of the above would be great!

    PS: One thing I thought about was passing along filter values in the postback which would have to be recognizable. That way the server could use them for selection and then create the filters and autoselect the previously selected filtervalues. I'm not quite sure how to acheive this though...

  2. Answer
    Daniel
    Admin
    Daniel avatar
    4943 posts

    Posted 14 Aug 2009 Link to this post

    Hello Datamex,

    We don't have a demo or code-library that demonstrates how to achieve such complex functionality. Regarding the depicted problems:

    - When I create the filters runtime, events are lost because the controls get recreated each postback.
    I suppose you already know that this is the way the ASP.NET page lifecycle works. You should reattach the event handlers on each postback.

    - I could place the filters in PreInit which should solve this, but then determining which controls should be loaded becomes a problem since loading all environment vars isn't finished yet?
    A better place to attain that is in the Page Load event handler where the ViewState will already be loaded.

    The following link will shed some light on the RadGrid's lifecycle: Event sequence

    As far as I understand, you will have to handle the filtering operations manually. You can use the RadGrid's API to get the filter expressions from the columns, although as I explained above you should filter the data on your own.

    Most probably you will have to modify the default look and feel of the filtering item - therefore we recommend you examine the links shown below:

    Filter template
    Google-like filtering
    Implementing filtering for template/custom columns
    Custom option for filtering (FilterListOptions -> VaryByDataTypeAllowCustom)
    Custom filter options with handling

    Filtering Template Columns demo
    Google-like Filtering demo

    Finally, I would like to point, that you could submit a code-library that demonstrates this functionality as soon as you complete it - your efforts will be rewarded.

    Best regards,
    Daniel
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
  3. UI for ASP.NET Ajax is Ready for VS 2017
  4. Datamex
    Datamex avatar
    161 posts
    Member since:
    Jun 2012

    Posted 17 Aug 2009 Link to this post

    Hi Daniel,

    thanks for your reply. We've got it working now, and if I may say so, it work's pretty damn good :)

    Here's what we've done:

    A RadGrid is placed on the page with a default LinqDataSource which supplies items. At first; the page is filtered by group, which ID is passed along using the querystring (all default stuff).

    A user control is also placed on the page. This user controls also uses the groupID to fetch rows from the database. These rows have the following columns:
    • FieldName: which field of the items should be filtered
    • Description: the description label of the filter
    • GroupID: the group this filter is linked to
    • FilterType: if this filter is a combo, panel, etc.
    • SortOrder: integer to sort the filters by

    So with the given groupID, the user control can retrieve all the field which should be filtered.

    Now the filters are added to the page during OnInit of the user control. Each filter is it's own composite control with either a RadPanel, RadCombo or other filter control inside of it. Each composite control implements a base class which has a string property called Filter which is filled with the value the user might have selected (or empty). The filter also implements an event FilterChanged which goes off when the user actually selects a value from the filter.

    When a filter changes; the user control which contains all the filters builds up a where predicate as follows:
    "Field1 == 'Value1' and Field2 == 'Value2"

    Now the user control also has a "FiltersChanged" event. This event is linked to an event handler on the page, which rebinds the grid. Now when the grid rebinds, in the OnSelecting event of the LinqDataSource, the following code is executed:

    FilterControl FilterControl = (FilterControl)CategoryFormView.FindControl("FilterControl");  
     
    string featureWhere = FilterControl.GetFilterString();  
     
    var nonParentItems = (from i in context.VwItems  
                                  where  
                                    i.IsActive == true &&  
                                    i.ParentItem == null &&  
                                    i.GroupID == groupID  
                                  select i)  
                                  .Where(featureWhere);  
     
    e.Result = nonParentItems; 

    By the way, passing along a where predicate as a string is non-default. I've got an extension class for Linq queries which makes this possible (search for dynamic Linq at Google).

    So now the filtered items are retrieved and bound to the grid as usual. The next time a user changes a filter, the whole process is repeated. Actually it's a bit more complicated; because when one of the filters is set; the rest get's a rebind too because some options might have disappeared by selecting a filter (since that will limit the number of items).

    The filter themselves use a Linq query to dynamically get the items which should be the options of the filter:

          var features = (from f in db.VwItems  
                          where f.Group.GroupID == GroupID == GroupID  
                          select f);  
     
          if (!String.IsNullOrEmpty(this.Filter))  
            features = features.Where(this.Filter);  
     
          var featureArray = features  
                            .Select<string>(CustomField)  
                            .Distinct()  
                            .Where(f => f != null).ToArray(); 

    The "CustomField" string represents the field which should be queried. The only restriction is that the database record (which is where the string comes from) should represent an existing field.


    So now if I want to add a filter: I simply add a record to the database telling which field should be filtered with what kind of filter. The site will automatically render an extra filter with the actual values present in the database, and all other filter will adapt to the chosen filtervalue to limit their options to whatever is actually available.


    I hope this is clear enough, if not please ask :) If wanted I can provide a little demo project, but that would take some time to create (and we're a bit busy finishing the project itself right now).
  5. Daniel
    Admin
    Daniel avatar
    4943 posts

    Posted 21 Aug 2009 Link to this post

    Hello Datamex,

    Thank you for the exhaustive explanation. I'm confident that a code-library project that demonstrate how to create such dynamic filters will surely be useful for our community and will be a valuable addition to our code-library. Of course your efforts will be rewarded.

    For more information how to submit a code-library, please examine the following link:
    Using the Code Library

    Best regards,
    Daniel
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Check out the tips for optimizing your support resource searches.
Back to Top