简体   繁体   中英

Binding DataTable To GridView, But No Rows In GridViewRowCollection Despite GridView Population?

Problem: I've coded a GridView in the markup in a page. I have coded a DataTable in the code-behind that takes data from a collection of custom objects. I then bind that DataTable to the GridView. (Specific problem mentioned a couple code-snippets below.)

GridView Markup:

<asp:GridView ID="gvCart" runat="server" CssClass="pList" AutoGenerateColumns="false" DataKeyNames="ProductID">
        <Columns>
            <asp:BoundField DataField="ProductID" HeaderText="ProductID" />
            <asp:BoundField DataField="Name" HeaderText="ProductName" />
            <asp:ImageField DataImageUrlField="Thumbnail" HeaderText="Thumbnail"></asp:ImageField>
            <asp:BoundField DataField="Unit Price" HeaderText="Unit Price" />
            <asp:TemplateField HeaderText="Quantity">
                <ItemTemplate>
                    <asp:TextBox ID="Quantity" runat="server" Text="<%# Bind('Quantity') %>" Width="25px"></asp:TextBox>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:BoundField DataField="Total Price" HeaderText="Total Price" />
        </Columns>
    </asp:GridView>

DataTable Code-Behind:

private void View(List<OrderItem> cart)
    {
        DataSet ds = new DataSet();
        DataTable dt = ds.Tables.Add("Cart");

        if (cart != null)
        {
            dt.Columns.Add("ProductID");
            dt.Columns.Add("Name");
            dt.Columns.Add("Thumbnail");
            dt.Columns.Add("Unit Price");
            dt.Columns.Add("Quantity");
            dt.Columns.Add("Total Price");

            foreach (OrderItem item in cart)
            {
                DataRow dr = dt.NewRow();

                dr["ProductID"] = item.productId.ToString();
                dr["Name"] = item.productName;
                dr["Thumbnail"] = ResolveUrl(item.productThumbnail);
                dr["Unit Price"] = "$" + item.productPrice.ToString();
                dr["Quantity"] = item.productQuantity.ToString();
                dr["Total Price"] = "$" + (item.productPrice * item.productQuantity).ToString();

                dt.Rows.Add(dr);
            }

            gvCart.DataSource = dt;
            gvCart.DataBind();
            gvCart.Width = 500;

            for (int counter = 0; counter < gvCart.Rows.Count; counter++)
            {
                gvCart.Rows[counter].Cells.Add(Common.createCell("<a href='cart.aspx?action=update&prodId=" +
                    gvCart.Rows[counter].Cells[0].Text + "'>Update</a><br /><a href='cart.aspx?action='action=remove&prodId=" +
                    gvCart.Rows[counter].Cells[0].Text + "/>Remove</a>"));
            }
        }
    }

Error occurs below in the foreach - the GridViewRowCollection is empty!

private void Update(string prodId)
    {
        List<OrderItem> cart = (List<OrderItem>)Session["cart"];
        int uQty = 0;

        foreach (GridViewRow gvr in gvCart.Rows)
        {
            if (gvr.RowType == DataControlRowType.DataRow)
            {
                if (gvr.Cells[0].Text == prodId)
                {
                    uQty = int.Parse(((TextBox)gvr.Cells[4].FindControl("Quantity")).Text);
                }
            }
        }

Goal: I'm basically trying to find a way to update the data in my GridView (and more importantly my cart Session object) without having to do everything else I've seen online such as utilizing OnRowUpdate, etc. Could someone please tell me why gvCart.Rows is empty and/or how I could accomplish my goal without utilizing OnRowUpdate, etc.? When I execute this code, the GridView gets populated but for some reason I can't access any of its rows in the code-behind.

The reason for you error is because you are checking

if (gvr.Cells[0].Text == prodId)

gvr in there is gvCart.Rows, so you need to define the index of the row before you can reference its Cells.

Kind of like:

if (gvr[i].Cells[0].Text == prodId)

You have to define index number of row to identify it individually. The following lines

if (gvr.Cells[0].Text == prodId)
 {
       uQty = int.Parse(((TextBox)gvr.Cells[4].FindControl("Quantity")).Text);
 }

should be like this:

if (gvr[i].Cells[0].Text == prodId)
 {
     uQty = int.Parse(((TextBox)gvr.Cells[4].FindControl("Quantity")).Text);
 }

I copied your code, supplied the View method with a list of CartItem objects on Postback, and it worked -- the code entered the loop as expected. The only change I made was comment out the Thumbnail b/c I didn't want to bother with an image. Otherwise, I kept both the markup and the your code behind. Is the list that you pass to View definitely not empty? Maybe if you could clarify the logic flow, I could offer something more. As a side note, why do you bother with creating a dataset and datatable? Would it not be easier to just bind the list to the grid directly?

So it's a good thing when I was coding this project that I started my day off right with a big bowl of FAIL for breakfast. I needed to do a DataBind() in the Page_Load(), or else the program would think that the GridView wasn't there. Problem solved. Thank you to everyone who tried to help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM