dynamically generated checkboxes' checked property appears as false, regardless of their actual state

StackOverflow https://stackoverflow.com/questions/11412175

  •  20-06-2021
  •  | 
  •  

Question

I have an asp:Table that is populated with "products" using controls on the page (an 'add' button and a textbox for quantity). In my code behind, whenever a table item is to be added, I first create an instance of Product, set its properties, and then add it to a list of products. I then do the following with the table: - Clear its Rows collection - Add the header row - Bind the table to the list of Products - Cache the list of Products, for later use

Each row in the Table begins with a cell containing a checkbox. Beneath the Table is a "Clear All" LinkButton. When the Clear All LinkButton is clicked, I direct it to a method to cycle through all of the CheckBoxes, determine whether or not they are checked, and delete the corresponding entry in the Product list if checked == true. So, in theory, when I re-bind the Products list to the Table, the Rows with that had their CheckBoxes selected should be removed.

This works if there is a single Row in the Table: when debugging, the CheckBox's checked property shows as "true", and the row is removed. However, if there is more than one row, the checked property for all CheckBoxes appears as "false", and nothing is removed.

EDIT - It actually appears to remove the last row of the table, though the rest of the CheckBoxes are treated as not being checked.

Here is the table on the page:

<asp:Table ID="tblProducts" runat="server">
<asp:TableHeaderRow ID="tblProductsHead" runat="server" BorderStyle="Solid">
    <asp:TableHeaderCell ID="colCheckBox" runat="server" Text="">
        <asp:CheckBox ID="chkSelectAll" runat="server" Text="" />
    </asp:TableHeaderCell>
    <asp:TableHeaderCell ID="colProduct" runat="server" Text="Product"><asp:TableHeaderCell>
    <asp:TableHeaderCell ID="colValue" runat="server" Text="Value"></asp:TableHeaderCell>
    <asp:TableHeaderCell ID="colQuantity" runat="server" Text="Quantity"></asp:TableHeaderCell>
    <asp:TableHeaderCell ID="colTotalValue" runat="server" Text="Total Value"></asp:TableHeaderCell>
</asp:TableHeaderRow>
</asp:Table>
<asp:LinkButton ID="lbtnClearAll" runat="server" Text="Clear All" 
    onclick="lbtnClearAll_Click"></asp:LinkButton>

...and here are the relevent sections of the code-behind:

 private void ClearSelectedTableRows()
    {
        if (Cache["TableRows"] != null)
        {
            tableRows = Cache["TableRows"] as List<TableRow>;
            Cache.Remove("TableRows");

            TableRow row = new TableRow();
            CheckBox rowBox = new CheckBox();

            for (int i = 0; i < tableRows.Count; i++)
            {
                row = tblProducts.Rows[i+1]; // skip header row
                rowBox = row.Cells[0].Controls[0] as CheckBox;

                if (rowBox.Checked)
                    tableRows.RemoveAt(i);

            }

            TableRow headRow = tblProductsHead;
            tblProducts.Rows.Clear();
            tblProducts.Rows.Add(headRow);
            Cache.Insert("TableRows", tableRows, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);
            PopulateTable();                
        }
    }


private void PopulateTable()
    {
        if (Cache["TableRows"] != null)
        {
            List<TableRow> rows = Cache["TableRows"] as List<TableRow>;
            foreach (TableRow row in rows)
                tblProducts.Rows.Add(row);
        }
    }
Was it helpful?

Solution 2

Someone left an answer, saying that the controls needed IDs for their properties to be properly assessed, but then deleted it. This turned out to be the root of the issue anyway. After giving the checkboxes IDs in the creation code, it began to work after a fashion.

However, further problems were then caused by using the RemoveAt() method; I was using the count of the "tableRows" list for the length of the loop, while at the same time potentially changing the length of that list inside the loop.

Its fixed now, and here's the updated method:

    private void ClearSelectedTableRows()
    {
        if (Cache["TableRows"] != null)
        {
            tableRows = Cache["TableRows"] as List<TableRow>;
            Cache.Remove("TableRows");

            TableRow row = new TableRow();
            CheckBox rowBox = new CheckBox();
            List<TableRow> rowsToRemove = new List<TableRow>();
            for (int i = 0; i < tableRows.Count; i++)
            {
                row = tblProducts.Rows[i+1]; // skip header row
                rowBox = row.Cells[0].Controls[0] as CheckBox;

                if (rowBox.Checked)
                    rowsToRemove.Add(tableRows[i]);                    
            }

            foreach (TableRow removeRow in rowsToRemove)
            {
                if (tableRows.Contains(removeRow))
                    tableRows.Remove(removeRow);
            }

            TableRow headRow = tblProductsHead;
            tblProducts.Rows.Clear();
            tblProducts.Rows.Add(headRow);
            Cache.Insert("TableRows", tableRows, null, System.Web.Caching.Cache.NoAbsoluteExpiration, System.Web.Caching.Cache.NoSlidingExpiration);
            PopulateTable();                
        }            
    }

Thanks to those who helped, and thanks to the phantom answerer!

OTHER TIPS

I also think that your loop seems odd, and agree that you should also start with i=1. A quick answer would be using --i right after removing a row

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top