1

I am trying to do when the checkbox column in my gridview is marked, I get the row index. My gridview is in a repeater and when I setup the gridview, I put a DataKeyNames:

<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
                    <ItemTemplate>
<asp:Panel ID="pBody1" runat="server" CssClass="cpBody">
                            <asp:Label ID="lblBodyText1" runat="server" />
                            <!-- Grid view to show products based on each category -->
                            <asp:GridView ID="gvProduct" runat="server" AutoGenerateColumns="False" Width="998px" CellPadding="4" ForeColor="#333333" GridLines="None" ShowHeader="False" DataKeyNames="id">
                                <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
                                <Columns>
                                    <asp:TemplateField ItemStyle-HorizontalAlign="Center">
                                        <ItemTemplate>
                                            <asp:CheckBox ID="cbCheckRow" runat="server" />
                                        </ItemTemplate>
                                    </asp:TemplateField>
                                    <asp:BoundField DataField="name" HeaderText="Name" ItemStyle-Width="600px" />
                                    <asp:BoundField DataField="categoryName" HeaderText="Category" />
                                    <asp:TemplateField HeaderText="Quantity" ItemStyle-HorizontalAlign="Center">
                                        <ItemTemplate>
                                            <asp:TextBox ID="tbQuantity" runat="server" Width="60" Text='<%# DataBinder.Eval(Container.DataItem, "inventoryQuantity") %>'/>
                                        </ItemTemplate>
                                    </asp:TemplateField>

                                </Columns>
                            </asp:GridView>
                        </asp:Panel>
                        <asp:CollapsiblePanelExtender ID="cpe1" runat="server" TargetControlID="pBody1" CollapseControlID="pHeader1"
                            ExpandControlID="pHeader1" Collapsed="true" ImageControlID="imgArrows1"
                            CollapsedImage="~/Images/downarrow.jpg"
                            ExpandedImage="~/Images/uparrow.jpg" TextLabelID="lblHeaderText1" CollapsedText="Show"
                            ExpandedText="Hide" CollapsedSize="0"
                            ScrollContents="false">
                        </asp:CollapsiblePanelExtender>
                    </ItemTemplate>
                </asp:Repeater>
 <asp:LinkButton ID="lbnConfirm" runat="server" class="btn dark" style="float: right" OnClick="lbnConfirm_Click">Confirm</asp:LinkButton>

When my lbnConfirm is onclick, I perform this to get the row index and store them into a list:

 protected void lbnConfirm_Click(object sender, EventArgs e)
    {
        GridView gv = (GridView)Repeater1.FindControl("gvProduct") as GridView;
        foreach (GridViewRow gr in gv.Rows)
        {
            CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
            if (cb.Checked)
            {
                GridViewRow row = gv.SelectedRow;
                string prodID = this.gv.DataKeys[row].Value.ToString();
                List<DistributionStandardPackingUnitItems> distSPUList = new List<DistributionStandardPackingUnitItems>();
                //Store the prodIDs into list
            }

        }
    }

When I run the page, it told me object reference is not set to an instance at this line:

foreach (GridViewRow gr in gv.Rows)

Also the gv of this line:

string prodID = this.gv.DataKeys[row].Value.ToString(); 

told me that the gv does not contain a definition of missing reference. I thought I declared at the code above?

Edited Portion:

       protected void lbnConfirm_Click(object sender, EventArgs e)
    {
        foreach (RepeaterItem item in Repeater1.Items)
        {
            if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
            {
                Panel pnl = item.FindControl("pBody1") as Panel;
                GridView gv = pnl.FindControl("gvProduct") as GridView;
                foreach (GridViewRow gr in gv.Rows)
                {
                    CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
                    if (cb.Checked)
                    {
                        string prodID = gv.DataKeys[gr.RowIndex].Value.ToString();
                        tempList.Add(prodID);
                        for (int count = 0; count < tempList.Count; count++)
                        {
                            lblTest.Text = tempList[count] + ",";
                        }
                    }
                }
            }
        }
    }

2 Answers2

1

Your approach is right, however you need to consider few more things:

  1. You have to loop through the Repeater's items and find the Panel in each item.

  2. You have to find the GridView inside the Panel, not in the Repeater.

  3. You have to find the DataKey Value by RowIndex, not by row.

EDIT : To test, add a Label outside the repeater:

<asp:Label ID="lblTest" runat="server" Text=""></asp:Label>

Also change the code to display Id in the label.

After rewriting lbnConfirm_Click() method, it should look like below:

protected void lbnConfirm_Click(object sender, EventArgs e)
{
    List<string> tempList = new List<string>();
    foreach (RepeaterItem item in Repeater1.Items)
    {
        if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
        {
            Panel pnl = item.FindControl("pBody1") as Panel;

            GridView gv = pnl.FindControl("gvProduct") as GridView;
            foreach (GridViewRow gr in gv.Rows)
            {
                CheckBox cb = (CheckBox)gr.Cells[0].FindControl("cbCheckRow");
                if (cb.Checked)
                {
                    //GridViewRow row = gv.SelectedRow;
                    string prodID =  gv.DataKeys[gr.RowIndex].Value.ToString();
                    List<DistributionStandardPackingUnitItems> distSPUList = new List<DistributionStandardPackingUnitItems>();
                    //Store the prodIDs into list
                    tempList.Add(prodID);                        
                }

            }
        }
    }  

    lblTest.Text = string.Join(",", tempList);       
}

The code above worked fine in my test! Only you have to be careful not to rebind the repeater at postback in Page_Load().

Hope it helps!

afzalulh
  • 7,925
  • 2
  • 26
  • 37
  • I have added these codes to test whether the prodID getting is correct or not (check the edited portion again, sorry). However, no matter I checked on which products, it just keep returning me a weird value as in I have no idea where the value comes from. –  Dec 29 '13 at 09:26
  • Oh ya, I forgot to concatenate the prodID and that's why it keeps returning one value instead of a list. Thanks a lot! –  Dec 29 '13 at 09:36
  • However, it keeps looping the record over and over again. Let's say I got product 1,2,6,7 checked. It returns me 1,1,2,1,2,6,1,2,6,7. I guess at the first check, it returns me 1. At the second check, it returns me 1,2 and so on. I guess because I am using repeater and collapsible panel extender and that's why it keep looping over and over again. Is there any ways to fix this? –  Dec 29 '13 at 10:01
  • @Gwen - I think your test has some issues, you should not loop through the list inside loops. I have added test code for this which worked for me. Can you please check? – afzalulh Dec 29 '13 at 10:19
  • @afzaluluh Oh I see. I put the for-loop at the wrong place. So basically if I wanted to loop thru the list to get product details of each prodID, I should replace the lblTest.Text with for-loop? –  Dec 29 '13 at 10:34
  • Also for each row which has been checked, I also need to get the user input for textbox which store the quantity. So inside the if statement of cb.Checked, I put this: TextBox tbQuantity = pnl.FindControl("tbQuantity") as TextBox; quantity = tbQuantity.Text; However, it told me that object reference is not set to an instance of an object. Why is it so? –  Dec 29 '13 at 10:41
  • Exactly!That is the place I would put the for loop. – afzalulh Dec 29 '13 at 10:41
  • @Gwen the tbQuantity is not in panel, it is in gridview. Next to `string prodID = gv.DataKeys[gr.RowIndex].Value.ToString();` add this: `var tbQuantity = gr.FindControl("tbQuantity") as TextBox; if(tbQuantity !- null) quantity = tbQuantity.Text;` – afzalulh Dec 29 '13 at 10:48
  • Oh ya, the textBox is inside the gridview. Thanks alot! It works now. Really really thanks for your extra effort as I am asking extra questions regarding to this thread –  Dec 29 '13 at 11:03
0

get the row index in the RowDataBound event :

 protected void gvProduct_RowDataBound(Object sender, GridViewRowEventArgs e)
    {

       if(e.commandName=="select")
       {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            int index = e.Row.RowIndex;

            CheckBox chk = (CheckBox)e.Row.FindControl("cbCheckRow"); 
            int code = Convert.ToInt32(this.gvProduct.DataKeys[e.Row.RowIndex].Value);

        }
     }

    }
Sajad Karuthedath
  • 14,987
  • 4
  • 32
  • 49
  • But how I know whether the checkbox column is checked? as In I should move all the codes inside my lbnConfirm_onClick into here? –  Dec 29 '13 at 08:05
  • i have edited my answer...!! to help u know how to use datakeys to get values – Sajad Karuthedath Dec 29 '13 at 08:11
  • But at the gvProduct, it told not does not contain a definition of 'gvProduct' and no extension method accepting first argument type which I encountered the same thing using my code above. Also, I don't have button field in grid view so I can't use the command name. It just simply checkbox coulmn –  Dec 29 '13 at 08:14
  • check this link http://stackoverflow.com/questions/8717175/get-selecteddatakey-in-rowdatabound – Sajad Karuthedath Dec 29 '13 at 08:15
  • u must select the event RowDatabound from the Gridview properties – Sajad Karuthedath Dec 29 '13 at 08:16
  • Sorry, what do you mean? Is it when I mark the checkbox checked, I also need to click on the Select buttonField column? –  Dec 29 '13 at 08:18
  • It will only fire when you click the Select buttonfield – Sajad Karuthedath Dec 29 '13 at 08:22
  • Is there any possible ways to do like when I mark the checkbox checked, it straight away get the row index? Because that's what am I trying to do. –  Dec 29 '13 at 08:26
  • @Gwen , yes you can do. you have make one ajax call. – Chandan Kumar Dec 29 '13 at 08:41
  • @kumarch1 I amended my code as edited portion. However, the error message now was Object reference not set to an instance of an object. I have no idea how to call my gridview which is in my repeater when button is on click. –  Dec 29 '13 at 08:43