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

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. 


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);
            }
        }