Reputation: 620
I am trying to filter my gridview using textbox within my gridiview headerTemplate. I am currently using TextChanged event method, to execute this task, however when I execute the events method, I am unable to filter the gridiview based on the search input, in the 'txtID'
.
protected void grdAdjAMT_TextChanged(object sender, EventArgs e)
{
TextBox txtName = (TextBox)GridView1.Rows[(0)].FindControl("txtID");
string strConnString = ConfigurationManager.ConnectionStrings["####"].ConnectionString;
using (SqlConnection con = new SqlConnection(strConnString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "select u.[uID], u.[uForenames],
u.[uSurname], u.[uCompany], u.[uEmailAddress],
s.[sStartDate]
from [dbo].[UserDe]
where u.[uID] like '%" + txtName + "%'
order by s.[sStartDate] desc";
cmd.Connection = con;
con.Open();
GridView1.DataSource = cmd.ExecuteReader();
GridView1.DataBind();
con.Close();
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
BindGrid();
}
I debugged my script and found that the debugger only goes through the pageload and BindGrid method, but it does not go through the "grdAdjAMT_TextChanged" method. I also tried to debug the textChange method separately, and still nothing happens.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="uID" HeaderStyle-BackColor="#3AC0F2" HeaderStyle-ForeColor="White" CellPadding="4" ForeColor="#333333" GridLines="None" >
<AlternatingRowStyle BackColor="White" />
<Columns>
<asp:TemplateField HeaderText="ID" SortExpression="ID">
<HeaderTemplate>
<asp:Label ID="Label1" runat="server" Text="ID"></asp:Label><br />
<asp:TextBox ID="txtID" runat="server" OnTextChanged="grdAdjAMT_TextChanged" AutoPostBack="true"></asp:TextBox>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("uID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Any further advice would be very much appreciated. Thanks
Upvotes: 1
Views: 3297
Reputation: 801
If BindGrid();
is working on the same grid as grdAdjAMT_TextChanged()
you probably need to do:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
On a post back the Page_Load
runs before the OnTextChanged event. So if you're binding the grid on every post back its going to clear the search text in your grid. Then when it check the TextChanged its going to compare the empty string to the empty string and say no change, so it won't run the event.
You might also want to change:
TextBox txtName = (TextBox)GridView1.Rows[(0)].FindControl("txtID");
to:
TextBox txtName = (TextBox)GridView1.HeaderRow.FindControl("txtID");
Upvotes: 1
Reputation: 18863
You could create a JavaScript Function for example: If I have on my control OnClientClick="OnClientSelectedIndexChanged"
for example I would write the following:
<script type="text/javascript">
function OnClientSelectedIndexChanged(sender, args) {
__doPostBack('ddlSomeDropDownList', '');
}
</script>
Page_load
Event and if it's properly setup it will then hit the event in my case of the ddlSomeDropDownList
.Upvotes: 1
Reputation: 896
The short answer here is that what you want to achieve (retriving results that match the given filter) isn't possible using server-side code alone.
Being stateless, the ASP.NET runtime will only be aware of the values it receives from a form when posted to it, and the values that it creates when rendering the page. Therefore, without posting back i.e. via a 'Filter' button, it will have no idea whether the text changed at all. Indeed, the TextChanged
event only works due to the Viewstate
property, a potentially large base-64 encoded string that's embedded into a form by the runtime to hold the 'previous' values for controls, and the like.
Pressing a button is a client-side act, so the server knows nothing about it. A point to demonstrate this is that whereas there's a Control.KeyPress event in System.Windows.Forms
, there's no equivalent in System.Web.UI.WebControls
.
As already indicated in other answers, Javascript will be involved in your solution, capturing the key press and then firing a request to the server. I'd recommend researching that approach and posting new questions if you run in to problems there.
A couple of points I'd make about the 'normal' implementation of this sort of functionality:
You probably don't want to be creating a brand new request to the database each time a key is pressed. You could filter a pre-loaded data set in memory to improve response time, but this may not be appropriate where the data set is very large and the page is used frequently.
You might want to have a minimum number of characters in the Filter field before applying the filter. If you have thousands of records, a filter of all those starting with 'a' would not be particularly useful, not least as it would result in a large page. You could apply the filter only when the field has reached a certain length easily with Javascript.
Another common feature is applying the filter after a specific period of time (i.e. 500 milliseconds) without further input. If a user knows what they want to search for e.g. 'computer', then there's no point filtering on each letter (or 6 times, if you've got a minimum of 3 characters needed before applying the filter). If you wait a short time after input before applying the filter, whilst resetting the timer each time any key is pressed, then you'll not have several rapid refilterings going on, and such things can degrade user experience and sometimes result in incorrect results (i.e. the last filter to be applied isn't the last one to have been entered).
If you only remember one of these points, remember this one. Have a good look at the concept of SQL injection, and amend your code accordingly. There are articles everywhere about it, so it shouldn't be hard to explore, but it involves users entering malicious commands into input fields that then end up cascaded to the database, for example, putting '; drop table UserDe; '
into the seach field.
Upvotes: 1