我正在使用GridViews和数据库中的数据来构建书店。有复选框,每行都有一个数量文本框。我正在验证以确保检查至少一个复选框,并且在击中提交之前,选定的行具有数量输入。当用户命中提交时,应将所选数据填充到另一个GridView中。
我遇到的问题是,当我选择两本不同的书并击中提交时,在Gridview上填充的书籍只是两次重复一本书。
*当我提交时,lblerror文本仍在显示false的可见性。
这是提交按钮调用的片段:
protected void btnSubmit_Click(object sender, EventArgs e)
{
double saleCount = 0;
Processor p = new Processor();
Book objBook = new Book();
foreach (GridViewRow row in gvBooks.Rows)
{
CheckBox chkbx = (CheckBox)row.Cells[0].FindControl("cbBook");
string title = row.Cells[1].Text;
string authors = row.Cells[2].Text;
string isbn = row.Cells[3].Text;
DropDownList gvType = (DropDownList)row.Cells[4].FindControl("ddBookType");
DropDownList gvMethod = (DropDownList)row.Cells[5].FindControl("ddMethod");
TextBox qty = (TextBox)row.Cells[6].FindControl("txtQty");
String strType = Convert.ToString(gvType.Text);
String strMethod = Convert.ToString(gvMethod.Text);
if (chkbx.Checked && !(string.IsNullOrEmpty(qty.Text)))
{
panelHeader.Visible = false;
panelStudentInfo.Visible = false;
panelCampus.Visible = false;
panelCatalog.Visible = false;
panelStudentInfo2.Visible = true;
panelCampus2.Visible = true;
panelCatalog2.Visible = true;
gvBooks.Visible = false;
gvOrder.Visible = true;
panelButtons.Visible = false;
txtStudentID2.Text = txtStudentID.Text;
txtStudentName2.Text = txtStudentName.Text;
txtStudentAddr2.Text = txtStudentAddr.Text;
txtPhoneNo2.Text = txtPhoneNo.Text;
ddCampus2.Text = ddCampuses.Text;
lblError.Visible = false;
int quantity = Convert.ToInt32(qty.Text);
objBook.Title = title;
objBook.Authors = authors;
objBook.ISBN = isbn;
objBook.BookType = strType;
objBook.Method = strMethod;
objBook.Quantity = quantity;
objBook.Price = p.Calculate(isbn, strType, strMethod);
objBook.TotalCost = objBook.Price * objBook.Quantity;
orderList.Add(objBook);
saleCount += objBook.Quantity;
orderTotal = objBook.TotalCost + orderTotal;
p.UpdateDB(isbn, quantity, strMethod, objBook.TotalCost);
}
else
{
lblError.Text = "* Please select a book & enter a quantity";
lblError.Visible = true;
}
gvOrder.DataSource = orderList;
gvOrder.DataBind();
gvOrder.Columns[0].FooterText = "Totals";
gvOrder.Columns[5].FooterText = saleCount.ToString();
gvOrder.Columns[6].FooterText = orderTotal.ToString("C2");
}
}
您需要从此
更改代码Book objBook = new Book();
foreach (GridViewRow row in gvBooks.Rows)
{
....
到这个
foreach (GridViewRow row in gvBooks.Rows)
{
Book objBook = new Book();
.....
原因很简单。如果您在循环外创建书籍实例,并且在循环中,您将其属性设置并添加到列表中,在第二个循环中,您将将同一实例的属性更改为不同的值,并将第二次参考添加到第二个循环中列表。在循环的末尾,您的列表将对同一实例有许多引用,并且该单个实例将其属性设置为循环内读取的最后值。
如果您在每个循环中都在循环中声明并初始化书籍实例,则是添加到列表中的不同实例,每个实例都将具有自己的属性值。
查看您的代码,我认为IF检查后的所有代码甚至都应该在数据源的设置之外。
在这里,剥离了代码的布局以突出相关点。
protected void btnSubmit_Click(object sender, EventArgs e)
{
double saleCount = 0;
Processor p = new Processor();
// Prepare a list of errors
List<string> errors = new List<strig>();
foreach (GridViewRow row in gvBooks.Rows)
{
Book objBook = new Book();
....
if (chkbx.Checked)
{
// Probably it is better to check here also the quantity value
// not just for text in the textbox (it could be anything)
if(Int32.TryParse(qty.Text, out int quantity) && quantity > 0)
{
// We have at least one checkbox checked with a quantity, so no error!
.....
}
else
{
// We don't have a quantity, add book title to error list....
errors.Add($"Book {title} has no quantity!");
}
}
}
// Handle the errors, if any
if(errors.Count > 0)
{
lblError.Text = string.Join("<br/>, errors);
lblError.Visible = true;
}
else
{
lblError.Visible = false;
gvOrder.DataSource = orderList;
gvOrder.DataBind();
gvOrder.Columns[0].FooterText = "Totals";
gvOrder.Columns[5].FooterText = saleCount.ToString();
gvOrder.Columns[6].FooterText = orderTotal.ToString("C2");
}
}