我正在使用GridViews和数据库中的数据来建立书店。有复选框,每行都有一个数量文本框。我正在确认确保至少一个复选框已选中,并且选中的行在点击提交之前具有数量输入。当用户单击“提交”时,应将所选数据填充到另一个gridview中。
我遇到的问题是,当我选择两本不同的书并单击提交时,gridview中填充的书仅重复一本书两次。
*当我在提交时将可见性设置为false时,lblError文本仍然显示。
以下是“提交”按钮调用的摘要:
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");
}
}
答案 0 :(得分:2)
您需要从此更改代码
Book objBook = new Book();
foreach (GridViewRow row in gvBooks.Rows)
{
....
对此
foreach (GridViewRow row in gvBooks.Rows)
{
Book objBook = new Book();
.....
原因很简单。如果在循环外创建Book实例,然后在循环内设置它的属性并将其添加到列表中,则在第二个循环中,将同一实例的属性更改为不同的值,并再次将引用添加到名单。在循环结束时,您的列表将具有对SAME实例的许多引用,并且该单个实例的属性将设置为循环内读取的最后一个值。
如果在循环中声明和初始化Book实例,则在每个循环中,都有一个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");
}
}