TextBox TextChanged Events and CheckBoc CheckedChanged Events not firing within a gridview
<p>So I've got a databound grid view within a UpdatePanel.</p>

<p>The idea is that the user can change the data within the gridview then click a save button to update the data within the database. </p>

<p>However in order to know which rows have been changed I have a textChanged event associated with each textbox, but the event isn't being fired.</p>

<p>Here's the ASP code:</p>

<pre><code>&lt;asp:UpdatePanel ID="UpdatePanel1" runat="server"&gt;
&lt;ContentTemplate&gt;
    &lt;span&gt;To update your poducts simply change the details below and click Save...&lt;/span&gt;
    &lt;div class="ProductList"&gt;
        &lt;asp:GridView ID="ProductList" runat="server" AllowPaging="True" AutoGenerateColumns="False"
            BackColor="#FFFBD6" BorderColor="#FFCC66" BorderStyle="None" BorderWidth="1px"
            CellPadding="3" OnPageIndexChanged="ProductList_PageIndexChanged" OnPageIndexChanging="ProductList_PageIndexChanging"
            PagerSettings-Mode="NumericFirstLast" PageSize="5"&gt;
            &lt;FooterStyle BackColor="White" ForeColor="#990000" /&gt;
            &lt;Columns&gt;
                &lt;asp:TemplateField HeaderText="Name"&gt;
                    &lt;ItemTemplate&gt;
                        &lt;asp:TextBox ID="tbName" AutoPostBack="true" EnableViewState="true" runat="server" BorderStyle="None" OnTextChanged="TextBox_TextChanged"
                            Text='&lt;%# Bind("productName") %&gt;'&gt;&lt;/asp:TextBox&gt;
                        &lt;asp:HiddenField ID="HiddenField1" runat="server" Value='&lt;%# Eval("productID") %&gt;' /&gt;
                    &lt;/ItemTemplate&gt;
                &lt;/asp:TemplateField&gt;
                &lt;asp:TemplateField HeaderText="Description"&gt;
                    &lt;ItemTemplate&gt;
                        &lt;asp:TextBox ID="tbDesc" AutoPostBack="true" EnableViewState="true" runat="server" BorderStyle="None" OnTextChanged="TextBox_TextChanged"
                            Text='&lt;%# Bind("productDesc") %&gt;' TextMode="MultiLine"&gt;&lt;/asp:TextBox&gt;
                    &lt;/ItemTemplate&gt;
                &lt;/asp:TemplateField&gt;
                &lt;asp:TemplateField HeaderText="Price"&gt;
                    &lt;ItemTemplate&gt;
                        &lt;asp:TextBox ID="tbPrice" AutoPostBack="true" EnableViewState="true" runat="server" BorderStyle="None" OnTextChanged="TextBox_TextChanged"
                            Text='&lt;%# Bind("productPrice", "{0:C}") %&gt;'&gt;&lt;/asp:TextBox&gt;
                    &lt;/ItemTemplate&gt;
                &lt;/asp:TemplateField&gt;
                &lt;asp:TemplateField HeaderText="Select"&gt;
                    &lt;ItemTemplate&gt;
                       &lt;asp:CheckBox id="cbDelete"  AutoPostBack="true" EnableViewState="true" runat="server" /&gt;
                    &lt;/ItemTemplate&gt;
                &lt;/asp:TemplateField&gt;
            &lt;/Columns&gt;
            &lt;RowStyle ForeColor="#000066" /&gt;
            &lt;SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" /&gt;
            &lt;PagerStyle BackColor="beige" ForeColor="#000066" HorizontalAlign="Left" /&gt;
            &lt;HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" /&gt;
        &lt;/asp:GridView&gt;
    &lt;/div&gt;
    &lt;div class="ProductListButtons"&gt;
        &lt;asp:ImageButton AlternateText="Add" ToolTip="Add New Product" Width="30px" Height="30px"
            ImageUrl="~/Images/Add.png" ID="AddBtn" runat="server" OnClick="AddBtn_Click" /&gt;
        &lt;asp:ImageButton ID="DeleteBtn" runat="server" AlternateText="Delete" Height="30px"
            ImageUrl="~/Images/delete.png" ToolTip="Delete Selected" Width="30px" OnClick="DeleteBtn_Click" /&gt;
        &lt;asp:ImageButton AlternateText="Save Changes" ToolTip="Save Changes" Width="30px"
            Height="30px" ImageUrl="~/Images/save-icon.png" ID="SaveBtn" runat="server" OnClick="SaveBtn_Click" /&gt;

    &lt;/div&gt;
&lt;/ContentTemplate&gt;
&lt;Triggers&gt;
    &lt;asp:AsyncPostBackTrigger ControlID="ProductList" EventName="PageIndexChanged" /&gt;
    &lt;asp:AsyncPostBackTrigger ControlID="DeleteBtn" EventName="Click" /&gt;
&lt;/Triggers&gt;
</code></pre>

<p></p>

<p>And here's the C#:</p>

<pre><code>using System;
using System.Data;
using BusinessLogicLayer; 
using DataAccessLayer.Objects;
using System.Web.UI.WebControls;

public partial class Controls_ProductList : System.Web.UI.UserControl
{
public int StallID { get; set; }
bool[] rowChanged;
bool[] rowDeleted;

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack)
    {
        StallID = Convert.ToInt16(ViewState["StallID"].ToString());
    }
    int totalRows = ProductList.Rows.Count;
    rowChanged = new bool[totalRows];
    rowDeleted = new bool[totalRows];
    BindList();
    ViewState.Add("StallID", StallID);
}

public void BindList()
{
    StallHandler handler = new StallHandler();
    DataTable productList = handler.GetProductsByID(StallID);
    ProductList.DataSource = productList;
    ProductList.DataBind();
}

protected void TextBox_TextChanged(object sender, EventArgs e)
{
    TextBox thisTextBox = (TextBox)sender;
    GridViewRow thisGridViewRow = (GridViewRow)thisTextBox.Parent.Parent;
    int row = thisGridViewRow.RowIndex;
    rowChanged[row] = true;
}

protected void cbDelete_CheckedChanged(object sender, EventArgs e)
{
    CheckBox thisCheckbox = (CheckBox)sender;
    GridViewRow thisGridViewRow = (GridViewRow)thisCheckbox.Parent.Parent;
    int row = thisGridViewRow.RowIndex;
    rowDeleted[row] = true;
}

protected void Page_PreRender(object sender, EventArgs e)
{
    if (Page.IsPostBack)
    {
        ProductList.DataBind();
    }
}

protected void ProductList_PageIndexChanged(object sender, EventArgs e)
{
}

protected void ProductList_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    ProductList.PageIndex = e.NewPageIndex;
    ProductList.DataBind();
}

protected void AddBtn_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
    Response.Redirect("../StallHolder/AddProduct.aspx");
}

protected void DeleteBtn_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
    int totalRows = ProductList.Rows.Count;
    for (int r = 0; r &lt; totalRows; r++)
    {
        if (rowDeleted[r])
        {
            GridViewRow thisGridViewRow = ProductList.Rows[r];
            HiddenField hf1 = (HiddenField)thisGridViewRow.FindControl("HiddenField1");
            string ID = hf1.Value;
            StallHandler handler = new StallHandler();
            handler.DeleteProduct(Convert.ToInt16(ID));
        }
    }       
    BindList();
}

protected void SaveBtn_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
    int totalRows = ProductList.Rows.Count;
    for (int r = 0; r &lt; totalRows; r++)
    {
        if (rowChanged[r])
        {
            GridViewRow thisGridViewRow = ProductList.Rows[r];
            HiddenField hf1 = (HiddenField)thisGridViewRow.FindControl("HiddenField1");
            string ID = hf1.Value;
            TextBox tbName = (TextBox)thisGridViewRow.FindControl("tbName");
            string Name = tbName.Text;
            TextBox tbDesc = (TextBox)thisGridViewRow.FindControl("tbDesc");
            string Desc = tbDesc.Text;
            TextBox tbPrice = (TextBox)thisGridViewRow.FindControl("tbPrice");
            string Price = tbPrice.Text;
            //Code to update the database!
        }
    }
}
</code></pre>

<p>}</p>

<p>Sorry thats pretty code heavy but I have no idea what I'm doing wrong or where.</p>
