views:

629

answers:

5

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.

A: 

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)
VoodooChild
I appreciate the speedy responses, but I'm confused. The compiler isn't even entering into the foreach. When I hovered over "gvCart.Rows" and observed the "Count" attribute, it was 0. That's what I'm stumped on.
KSwift87
can you please give overview of how you are calling each of you methods?
VoodooChild
My guess is that your DataSource is not set up correctly.
VoodooChild
On my cart.aspx page, I look for a certain variable in the query string in the Page_Load which determines what method gets called e.g.:string action = Request.QueryString["action"];string prodId = Request.QuerySTring["prodId"];if(action == "update"){ this.Update(prodId);}else if (action == "remove"){ this.Remove(prodId);}Anyway if my DataSource weren't properly set up, wouldn't I get an improper amount (most likely 0) visible rows in the GridView? Data in my GridView is visible, but I can't access the amount of rows after one of my buttons gets clicked. :-(
KSwift87
A: 

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);
 }
Johnny
I appreciate the speedy responses, but I'm confused. The compiler isn't even entering into the foreach. When I hovered over "gvCart.Rows" and observed the "Count" attribute, it was 0. That's what I'm stumped on.
KSwift87
foreach (GridViewRow gvr in gvCart.Rows)Should be likeforeach (GridViewRow gvr in gvCart.Rows.Count)
Johnny
that won't work, read his question: it says Count is 0 for the rowcount.
VoodooChild
A: 

As per my understanding..u r clickng an "update" link in gridview and goto new page...cart.aspx...where u access "update" function. Is tat correct?

Anish
Did your issue get solved?
Anish
No sorry I had to get some sleep. lol :-). Anyway Anish you're mostly right, except I'm not going to a new page via the update link. The update link takes me to the same page and passes a product ID in the query string. My plan was to take the product ID and figure out what row of the GridView the ID came from, and then grab the updated quantity from that same row.
KSwift87
A: 

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?

Antony Highsky
I tried binding directly, but couldn't access the columns to change the column name. :-( Anyway the list is DEFINITELY not empty. If it were empty, then the GridView wouldn't populate. The GridView populates fine from the List/DataTableI'm feeding it, just for whatever reason when I do a postback via my Update link, it thinks the GridView.Rows collection is empty. :-(
KSwift87
A: 

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.

KSwift87