-1

I’m working on an ASP.NET WebForms application where I want to add a search box on top of each column header in a grid. The search box is supposed to filter the grid data based on user input.

Here’s what I’ve implemented so far:

  • I have placed TextBox controls inside the grid’s header template for each column.

  • I am handling the search operation using the OnTextChanged event in the ASPX.CS file and also tried with JavaScript in the ASPX file.

Problem:

The search boxes are displayed on the grid, but I am unable to type into them. They appear to be uneditable, and I’m not sure why the input fields are not working as expected.

$(document).ready(function () {
    Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);

    function EndRequestHandler(sender, args) {
        var rows1 = $('table#<%= Table1.ClientID %> tr:last').index() + 1;

        if (rows1 > 1) {
            // Initialize DataTable with column-based search functionality
            var table = $("#<%=Table1.ClientID%>").DataTable({
                stateSave: true,
                pagingType: "full_numbers",
                lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
                dom: '<"top"Bfl>rt<"bottom"ip><"clear">',
                buttons: [
                    { extend: 'copy', className: 'btn-sm btn-default' },
                    { extend: 'excel', className: 'btn-sm btn-success', filename: function () { return getExportFileName(); } },
                    { extend: 'print', className: 'btn-sm btn-danger' }
                ],
                responsive: false,
                retrieve: false,
                ordering: false,
            });

            // Apply search on each column
            $("#<%=Table1.ClientID%> thead input.search-column").on('keyup change', function () {
                var colIndex = $(this).closest('th').index();  // Get the index of the column
                table.column(colIndex).search(this.value).draw();  // Perform search
            });
        }
    }

    Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(function (evt, args) {
        var rows1 = $('table#<%= Table1.ClientID %> tr:last').index() + 1;

        if (rows1 > 1) {
            var table = $("#<%=Table1.ClientID%>").DataTable({
                stateSave: true,
                pagingType: "full_numbers",
                lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
                dom: '<"top"Bfl>rt<"bottom"ip><"clear">',
                buttons: [
                    { extend: 'copy', className: 'btn-sm btn-default' },
                    { extend: 'excel', className: 'btn-sm btn-success', filename: function () { return getExportFileName(); } },
                    { extend: 'print', className: 'btn-sm btn-danger' }
                ],
                responsive: false,
                retrieve: false,
                ordering: false,
            });

            // Apply search on each column on initial load
            $("#<%=Table1.ClientID%> thead input.search-column").on('keyup change', function () {
                var colIndex = $(this).closest('th').index();
                table.column(colIndex).search(this.value).draw();
            });
        }
    });
});

1 Answer 1

1

Without seeing your markup, it becomes very difficult to guess or see why your textboxes can't receive the focus.

I as a general rule suggest you place the search (and controls) above the GridView, and not place them in the header. Keep in mind that when you re-bind the GridView, the control values will be lost when such controls are in the heading (they don't persist when you re-bind the data of which you be doing for the filter).

However, here is a working GridView example:

Markup:

        <asp:GridView ID="GVHotels" runat="server" AutoGenerateColumns="False"
            DataKeyNames="ID" CssClass="table table-hover" Width="50%">
            <Columns>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:Label ID="lblFirst" runat="server" 
                            Text='<%# Eval("FirstName") %>'></asp:Label>
                    </ItemTemplate>
                    <HeaderTemplate>
                        First Name<br />
                        <asp:TextBox ID="txtSearchFirst" runat="server"
                            OnTextChanged="txtSearchFirst_TextChanged"
                            AutoPostBack="true">
                        </asp:TextBox>
                    </HeaderTemplate>
                </asp:TemplateField>
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:Label ID="lblLast" runat="server" 
                            Text='<%# Eval("LastName") %>'></asp:Label>
                    </ItemTemplate>
                    <HeaderTemplate>
                        Last Name<br />
                        <asp:TextBox ID="txtSearchLast" runat="server"
                            OnTextChanged="txtSearchLast_TextChanged"
                            AutoPostBack="true">
                        </asp:TextBox>
                    </HeaderTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="City" HeaderText="City" />
                <asp:TemplateField>
                    <ItemTemplate>
                        <asp:Label ID="lblHotel" runat="server" 
                            Text='<%# Eval("HotelName") %>'></asp:Label>
                    </ItemTemplate>
                    <HeaderTemplate>
                        Hotel<br />
                        <asp:TextBox ID="txtSearchHotel" runat="server"
                            OnTextChanged="txtSearchHotel_TextChanged"
                            AutoPostBack="true">
                        </asp:TextBox>
                    </HeaderTemplate>
                </asp:TemplateField>
                <asp:BoundField DataField="Description" HeaderText="Description" />
            </Columns>                
        </asp:GridView>
        <asp:TextBox ID="TextBox1" runat="server" style="border:none"></asp:TextBox>

And code behind is:

    protected void Page_Load(object sender, EventArgs e)
    {

        if (!IsPostBack)
        {
            string strSQL =
                "SELECT * FROM tblHotelsA " +
                "ORDER BY HotelName";

            DataTable rstData = General.MyRst(strSQL);
            GVHotels.DataSource = rstData;
            GVHotels.DataBind();
        }
    }

    protected void txtSearchFirst_TextChanged(object sender, EventArgs e)
    {
        LoadGrid(sender);
        
    }

    protected void txtSearchLast_TextChanged(object sender, EventArgs e)
    {
        LoadGrid(sender);
    }

    protected void txtSearchHotel_TextChanged(object sender, EventArgs e)
    {
        LoadGrid(sender);
    }

    void LoadGrid(object sender)
    {
        TextBox cSend = (TextBox)sender;

        TextBox sFirst = (TextBox)GVHotels.HeaderRow.FindControl("txtSearchFirst");
        TextBox sLast = (TextBox)GVHotels.HeaderRow.FindControl("txtSearchLast");
        TextBox sHotel = (TextBox)GVHotels.HeaderRow.FindControl("txtSearchHotel");

        string strSQL = "SELECT * FROM tblHotelsA ";
        string strWhere = "";

        SqlCommand cmdSQL = new SqlCommand("");

        if (sFirst.Text != "")
        {
            strWhere = "(FirstName LIKE @First + '%') ";
            cmdSQL.Parameters.Add("@First", SqlDbType.NVarChar).Value = sFirst.Text;
        }

        if (sLast.Text != "")
        {
            if (strWhere != "") strWhere += " AND ";

            strWhere += "(LastName LIKE @Last + '%') ";
            cmdSQL.Parameters.Add("@Last", SqlDbType.NVarChar).Value =sLast.Text;
        }

        if (sHotel.Text != "")
        {
            if (strWhere != "") strWhere += " AND ";

            strWhere += "(HotelName LIKE @Hotel + '%') ";
            cmdSQL.Parameters.Add("@Hotel", SqlDbType.NVarChar).Value =sHotel.Text;
        }

        if (strWhere != "") strWhere = " WHERE " + strWhere;

        cmdSQL.CommandText = strSQL + strWhere + " ORDER BY HotelName";

        GVHotels.DataSource = General.MyRstP(cmdSQL);
        GVHotels.DataBind();

        // with a grid re-bind, then the header text boxes are lost, so lets 
        // restore them

        TextBox sFirstR = (TextBox)GVHotels.HeaderRow.FindControl("txtSearchFirst");
        TextBox sLastR = (TextBox)GVHotels.HeaderRow.FindControl("txtSearchLast");
        TextBox sHotelR = (TextBox)GVHotels.HeaderRow.FindControl("txtSearchHotel");

        sFirstR.Text = sFirst.Text;
        sLastR.Text = sLast.Text;
        sHotelR.Text = sHotel.Text;

        // we assume user just hit tab key, and with a post-back then text box focus
        // will be re-set, so let's move cursor to the next text box in the gv header
        if (cSend.ID == "txtSearchFirst") sLastR.Focus();
        if (cSend.ID == "txtSearchLast") sHotelR.Focus();
        if (cSend.ID == "txtSearchHotel") sFirstR.Focus();

    }

And thus the result is this:

enter image description here

Note how we have to "restore" the text boxes if we re-bind the GridView. If you place the controls outside of the GridView, then such code will not be required.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.