Text Filtering with Dynamic Data

Text Filtering with Dynamic Data

Rate This
  • Comments 15

Dynamic Data provides a good architecture for adding custom filters to your application. To read more about understanding filtering read the following post

In this post I am going to take you through a walkthrough of how you can write your own search filter. This sample builds on writing LinqExpressions. If you want more information about Linq Expressions you can learn more from here

1. Add a FilterUserControl  called “Search” to the DynamicData/Filters template(You can use the one attached to this post)

The Search user control has a textbox which takes in the search input and a button control

2. In the Code behind of search.ascx override the GetQueryable() method to return the filtered query as follows

public override IQueryable GetQueryable(IQueryable source)
    {

        if (Column.TypeCode != TypeCode.String)
            return source;


        string searchString = TextBox1.Text;
        if (TextBox1.Text == "")
            searchString = String.Empty;
        Type type = typeof(String);



        string searchProperty = Column.DisplayName;
        ConstantExpression searchFilter = Expression.Constant(searchString);


        ParameterExpression parameter = Expression.Parameter(source.ElementType);
        MemberExpression property = Expression.Property(parameter, this.Column.Name);
        if (Nullable.GetUnderlyingType(property.Type) != null)
        {
            property = Expression.Property(property, "Value");

        }
        MethodInfo method = typeof(String).GetMethod("Contains", new[] { typeof(String) });

        var containsMethodExp = Expression.Call(property, method, searchFilter);
        var containsLambda = Expression.Lambda(containsMethodExp, parameter);


        var resultExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, Expression.Quote(containsLambda));

        return source.Provider.CreateQuery(resultExpression);

    }
3. Add an event to Raise the Filter changes event. In this sample it is the ButtonClicked() event as shown
 
 protected void Button1_Click(object sender, EventArgs e)
    {
        OnFilterChanged();
    }

4. Add FilterUIHint(“Search”) to a string column eg. ProductName column in Products table of Northwind database.

You can download this sample that has the Search.ascx user control from here

Leave a Comment
  • Please add 4 and 5 and type the answer here:
  • Post
  • It`s great, i`ve been trying this for hours, but i was freeze in GetQueryable method, however, i would like this control to have a single instance for all fields i decore with the FilterUIHint attrbute, can you give me a clue on how to do this?.

    Tanks in advance.

  • Can you please explain more what you want. Every instance of FilterUiHint is tied to a column that it filters on.

  • Hi !!

    I followed the Oleg's tutorial but I noticed I can filter only columns from Table "Orders" , how can I switch to another table? , you did it with the table Products...

  • You need to put the FilterUIHint(msdn.microsoft.com/.../dd411802.aspx) to column of the table you want to filter by

  • Thanks, worked for me first try :-)

  • I forgot to mention I did have to change one line to get it to compile (I'm using pre-release 4 of DD4 because I can't get the admins to install .NET 40 yet)

    Changed:

    Expression.Parameter(source.ElementType);

    to:

    Expression.Parameter(source.ElementType, string.Empty);

  • Hi pranav,

    You have a great work and have a top rank in google search

    I’ve deployed your coding but it is a case sensitive search

    How can I use case in-sensitive search ? Please kindly advise.

    System.StringComparison.OrdinalIgnoreCase

    Thank you so much

  • Can you do the same for an int column?

    Thanks for a great article.

  • Hi mb.  FYR below.  It is a integer exact match

    Any experts can advise the case insensitive search ? many thx

       public override IQueryable GetQueryable(IQueryable source)

       {

           int searchInt =  0 ;

           // Match DB Column Type = Integer

               if (Column.TypeCode != TypeCode.Int32)

                   return source;

               if (String.IsNullOrEmpty(TextBox1.Text))

                   return source;

               if (int.TryParse(TextBox1.Text, out searchInt) == false)

                       TextBox1.ToolTip = "Input correct code";

           Type type = typeof(Int32);

           string searchProperty = Column.DisplayName;

           ConstantExpression searchFilter = Expression.Constant(searchInt);

           ParameterExpression parameter = Expression.Parameter(source.ElementType);

           MemberExpression property = Expression.Property(parameter, this.Column.Name);

           if (Nullable.GetUnderlyingType(property.Type) != null)

           {

               property = Expression.Property(property, "Value");

           }

           MethodInfo method = typeof(Int32).GetMethod("Equals", new[] { typeof(Int32) });

           var containsMethodExp = Expression.Call(property, method, searchFilter);

           var containsLambda = Expression.Lambda(containsMethodExp, parameter);

           var resultExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, Expression.Quote(containsLambda));

           return source.Provider.CreateQuery(resultExpression);

       }

       protected void Page_Load(object sender, EventArgs e)

       {

           this.TextBox1.ToolTip = this.Column.DisplayName;

           this.validator.ErrorMessage = "Invalid number format specified for " +

                     this.Column.DisplayName;

                 this.validator.ToolTip = this.validator.ErrorMessage;

       }

       protected void Validate(object sender, ServerValidateEventArgs e)

       {

         int value;

         e.IsValid = int.TryParse(e.Value, out value);

       }

  • Thanks for the code :)

    I don't get it to work though:

    I added the Search.aspx, Search.aspx.cs, Search.aspx.designer.cs etc and in Annotations.cs I set

    public class Customer_ReportingMetaData

       {

           [DisplayName("Customer Id")]

           [UIHint("TextReadOnly")]

           [FilterUIHint("Search")]

           public int CustomerId { get; set; }

    it compiles but the search textbox is not showing up, what magic is it that will show it?

    I guess I'm missing something.

  • Hi,

    Thanks for a very good post.

    I have a question though, I have downloaded and added the "Search" FilterUserControl, but how do I use it? I want the textbox search instead of a dropdown list used in this code:¨

    <asp:FilterRepeater ID="FilterRepeater" runat="server">

                   <ItemTemplate>

                       <asp:Label runat="server" Text='<%# Eval("DisplayName") %>' AssociatedControlID="DynamicFilter$DropDownList1" />

                       <asp:DynamicFilter runat="server" ID="DynamicFilter" OnSelectedIndexChanged="OnFilterSelectedIndexChanged" />

                   </ItemTemplate

              </asp:FilterRepeater>

    How do I rewrite the above code to use the "Search" user control (textbox + button) instead of the dropdownlist above? I know I have to tie the Search user control to one or multiple database columns, but at the moment I cannot see the textbox.

    Would be grateful for advice.

  • Hi, Having problem in downloading Search.ascx control, can you pls provide alternate location to get it.

    Thanks

  • Kushi,

    can you please try again. I just tried the link and it is accessible.

  • Hi, Pranav,

    When i click "here" this is the link its opening 'skydrive.live.com/.../TextSearchFilter and showing page cannot be displayed.

    Anyway can u pls update me whether using FilterUIHint(“Search”) in VS2008 is possible?

    When i google it comes under V4.0

  • Is it possible to change the column value to upper and then do the search in the above code, if yes can you suggest me how this can be modified?

    I want something like below

    Upper(columnName) Like Upper('%somevalue%')

Page 1 of 1 (15 items)