I found when getting this to work. Have a look at the code snippets
<div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<span>To update your poducts simply change the details below and click Save...</span>
<div class="ProductList">
<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">
<FooterStyle BackColor="White" ForeColor="#990000" />
<Columns>
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:TextBox ID="tbName" AutoPostBack="false" EnableViewState="true" runat="server" BorderStyle="None" OnTextChanged="TextBox_TextChanged"
Text='<%# Bind("productName") %>'></asp:TextBox>
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Eval("productID") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Description">
<ItemTemplate>
<asp:TextBox ID="tbDesc" AutoPostBack="false" EnableViewState="true" runat="server" BorderStyle="None" OnTextChanged="TextBox_TextChanged"
Text='<%# Bind("productDesc") %>' TextMode="MultiLine"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price">
<ItemTemplate>
<asp:TextBox ID="tbPrice" AutoPostBack="false" EnableViewState="true" runat="server" BorderStyle="None" OnTextChanged="TextBox_TextChanged"
Text='<%# Bind("productPrice", "{0:C}") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox id="cbDelete" OnCheckedChanged="cbDelete_CheckedChanged" AutoPostBack="false" EnableViewState="true" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<RowStyle ForeColor="#000066" />
<SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="beige" ForeColor="#000066" HorizontalAlign="Left" />
<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
</asp:GridView>
</div>
<div class="ProductListButtons">
<asp:ImageButton AlternateText="Add" ToolTip="Add New Product" Width="30px" Height="30px"
ImageUrl="~/Images/Add.png" ID="AddBtn" runat="server" OnClick="AddBtn_Click" />
<asp:ImageButton ID="DeleteBtn" runat="server" AlternateText="Delete" Height="30px"
ImageUrl="~/Images/delete.png" ToolTip="Delete Selected" Width="30px" OnClick="DeleteBtn_Click" />
<asp:ImageButton AlternateText="Save Changes" ToolTip="Save Changes" Width="30px"
Height="30px" ImageUrl="~/Images/save-icon.png" ID="SaveBtn" runat="server" OnClick="SaveBtn_Click" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
public partial class Controls_ProductList : System.Web.UI.UserControl
{
public int StallID { get; set; }
bool[] rowChanged;
bool[] rowDeleted;
// this allows me to test your code without your data source (C# 3.0 list constructor)
private static List<Product> _productList = new List<Product>() {
new Product() { productID = 1, productName = "Product 1", productDesc = "This is product 1", productPrice = 1.0m },
new Product() { productID = 2, productName = "Product 2", productDesc = "This is product 2", productPrice = 1.0m },
new Product() { productID = 3, productName = "Product 3", productDesc = "This is product 3", productPrice = 1.0m }
};
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
StallID = Convert.ToInt16(ViewState["StallID"].ToString());
}
else
{
// Only bind if this is not a postback
BindList();
}
int totalRows = ProductList.Rows.Count;
rowChanged = new bool[totalRows];
rowDeleted = new bool[totalRows];
ViewState.Add("StallID", StallID);
foreach (GridViewRow row in ProductList.Rows)
{
var checkBox = row.FindControl("cbDelete");
ScriptManager1.RegisterAsyncPostBackControl(checkBox);
}
}
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 < totalRows; r++)
{
if (rowDeleted[r])
{
GridViewRow thisGridViewRow = ProductList.Rows[r];
HiddenField hf1 = (HiddenField)thisGridViewRow.FindControl("HiddenField1");
int ID = Convert.ToInt16(hf1.Value);
//StallHandler handler = new StallHandler();
//handler.DeleteProduct(Convert.ToInt16(ID));
_productList = _productList.Where(a => a.productID != ID).ToList();
}
}
BindList();
}
protected void SaveBtn_Click(object sender, System.Web.UI.ImageClickEventArgs e)
{
int totalRows = ProductList.Rows.Count;
for (int r = 0; r < totalRows; r++)
{
if (rowChanged[r])
{
GridViewRow thisGridViewRow = ProductList.Rows[r];
HiddenField hf1 = (HiddenField)thisGridViewRow.FindControl("HiddenField1");
int ID = Convert.ToInt32(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!
var product = _productList.Where(a => a.productID == ID).First();
product.productName = Name;
product.productDesc = Desc;
product.productPrice = decimal.Parse(Price, System.Globalization.NumberStyles.Currency);
}
}
BindList();
}
}
public class Product
{
public int productID { get; set; }
public string productName { get; set; }
public string productDesc { get; set; }
public decimal productPrice { get; set; }
}
I had to create my own class to use as the data source to test this. Just remove those bits of code for your solution.
As you can see, I've made some changes:
- Set
AutoPostback="False"
for the check box and text boxes.
- Removed the
<Triggers>
element, as this only applies to controls outside the UpdatePanel
.
- Added the
OnCheckedChanged="cbDelete_CheckedChanged"
element to the check box.
Some minor changes also but none worth mentioning. Although I should mention I'm not a fan of the way you have done this, but it does seem to work.