Gridview with highlighted search results

25 Jun
June 25, 2008

Continuing on my Gridview series, the next project which had me reaching for Google was a requirement to highlight the returned search results in a Gridview.

Digging around, I found an article on 4guysfromRolla titled Highlighting Search Keywords in a DataGrid Web Control which formed the basis of my work.  I ended up updating, simplying and modifing the code and decided to write a quick tutorial on how to highlight the text that a user searched for in the search results:
Gridview with highlighted search results


Step 1: Create a Gridview

Create a simple Gridview with TemplateFields for the fields that you would like to search for.  In my example I called the Gridview Gridview1 and created a TemplateField for my two search fields, First Name and Last Name.  The other point of interest is that the Eval statement for these 2 fields is wrapped around a function that we’re going to write called HighlightText.

<asp:GridView ID="Gridview1" runat="server" AutoGenerateColumns="False" 
AllowPaging="True" AllowSorting="true" DataSourceID="dsGridview" Width="540px" 
    <asp:BoundField DataField="id" HeaderText="ID" SortExpression="id" />
    <asp:TemplateField HeaderText="First Name" SortExpression="FirstName">
        <ItemStyle Width="120px" HorizontalAlign="Left" />
            <asp:Label ID="lblFirstname" Text='<%# 
                HighlightText(Eval("FirstName")) %>' runat="server" />
    <asp:TemplateField HeaderText="Last Name" SortExpression="LastName">
        <ItemStyle Width="120px" HorizontalAlign="Left" />
            <asp:Label ID="lblLastname" Text='<%# 
            HighlightText(Eval("LastName")) %>' runat="server" />
    <asp:BoundField DataField="Department" HeaderText="Department"
        SortExpression="Department" ItemStyle-Width="130px" />
    <asp:BoundField DataField="Location" HeaderText="Location"
        SortExpression="Location" ItemStyle-Width="130px" />

Step 2: Create a datasource with a FilterExpression

In order to enable our search functionality, add a FilterExpression to the datasource.  The FilterExpression that I’m using checks for the first name and last name against the Search Text box which will be created shortly.  And yes, I know I shouldn’t use SQL statements in my Datasource, this is merely to make the example easier to demonstrate.  Normally I would use a multi-tier architecture with an ObjectDataSource such as something described by Imar Spaanjaars.

<asp:SqlDataSource ID="SqlDataSource1" runat="server" SelectCommand="SELECT * 
    FROM People" ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
    FilterExpression="firstname like '%{0}%' or lastname like '%{1}%'">
        <asp:ControlParameter Name="firstname" ControlID="txtSearch" 
        PropertyName="Text" />
        <asp:ControlParameter Name="lastname" ControlID="txtSearch" 
        PropertyName="Text" />

The % characters in the FilterExpression are a wildcard to match any text before or after the search expression.

Step 3: Add a Search Box

This bit is easy, just create a textbox that you call txtSearch – this is what is referenced in our FilterExpression in Step 2.

<asp:TextBox ID="txtSearch" runat="server" />
<asp:ImageButton ID="btnSearch" ImageUrl="images/searchbutton.png" 
runat="server" />
<asp:ImageButton ID="btnClear" ImageUrl="images/clearbutton.png" 
runat="server" />

Step 4: Add code

The comments in the code below should be self-explanatory.  Basically every time we’re displaying the First and Last name data in our Gridview, we check to see if there is any search text, and if there is, use a regular expression to enclose the search string in a CSS span which turns the text yellow.

Imports System.Text.RegularExpressions

Partial Class GridviewwithHighlightedSearch
    Inherits System.Web.UI.Page

    ' Create a String to store our search results
    Dim SearchString As String = ""

    Function HighlightText(ByVal InputTxt As String) As String
        ' This function is called whenever text is displayed in the FirstName
        ' and LastName fields from our database. If we're not searching then 
        ' just return the original input, this speeds things up a bit
        If SearchString = "" Then
            Return InputTxt
            ' Otherwise create a new regular expression and evaluate the 
            ' FirstName and LastName fields against our search string.
            Dim ResultStr As Regex
            ResultStr = New Regex(SearchString.Replace(" ", "|"), 
            Return ResultStr.Replace(InputTxt, New 
                 MatchEvaluator(AddressOf ReplaceWords))
        End If
    End Function

    Public Function ReplaceWords(ByVal m As Match) As String
        ' This match evaluator returns the found string and adds it a CSS 
        ' class I defined as 'highlight'
        Return "<span>" + m.ToString + "</span>"
    End Function

    Protected Sub btnClear_Click(ByVal sender As Object, ByVal e As  _
            System.Web.UI.ImageClickEventArgs) Handles btnClear.Click
        ' Simple clean up text to return the Gridview to it's default state
        txtSearch.Text = ""
        SearchString = ""
    End Sub

    Protected Sub btnSearch_Click(ByVal sender As Object, ByVal e As  _
            System.Web.UI.ImageClickEventArgs) Handles btnSearch.Click
        ' Set the value of the SearchString so it gets
        SearchString = txtSearch.Text
    End Sub
End Class

Step 5: Add the CSS class for highlighting

The final bit is to add the CSS claass referenced in the span called highlight.  In my case I’m simply turning the background of my text yellow:

<style type="text/css">
   .highlight {text-decoration: none;color:black;background:yellow;}

That’s it!

© Copyright - Evonet