Q:

Populated GridView is empty when I attempt to iterate through the rows

I have a GridView that I populate.  It appears correctly and shows the data.  It contains a Checkbox column, and my intent is when the user clicks a button on the form, it iterates through the rows of the GridView, and totals up all the rows the user has selected by checking the CheckBox.
(I got the details of how to do this from http://asp.net-informations.com/gridview/checkbox.htm)
The problem comes at this point, and I've discovered that just before it gets to the line
foreach (GridViewRow row in grdItems.Rows)

grdItems.Rows.Count = 0, even though the GridView is currently displaying data.
The GridView:
<asp:GridView ID="grdItems" AutoGenerateColumns="false" runat="server" >
    <Columns>
        <asp:TemplateField>
            <ItemTemplate>
                <asp:CheckBox ID="chkCtrl" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="Item_No" HeaderText="Item No" />
        <asp:BoundField DataField="Amount" HeaderText="Amount" />
    </Columns>
</asp:GridView>

The Button:
<asp:Button ID="cmdOK" runat="server" Text="Add" />

The Button Onclick:
protected void cmdOK_Click(object sender, EventArgs e)
{
    if (ValidateForm())
    {
        SaveP2P();
    }
}

The method the populates the GridView:
private void FillGrid()
{
    System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection("Snipped for privacy");
    conn.Open();
    System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand();
    cmd.CommandText = "Snipped for privacy";
    cmd.Connection = conn;
    System.Data.OleDb.OleDbDataAdapter adp = new System.Data.OleDb.OleDbDataAdapter(cmd);
    System.Data.DataSet ds = new System.Data.DataSet();
    adp.Fill(ds);
    adp.Dispose();
    cmd.Dispose();
    conn.Close();

    grdItems.DataSource = ds;
    grdItems.DataBind();

}

The ValidateForm() method which contains the code I'm struggling with
private bool ValidateForm()
{
    bool result = true;
    decimal TotalAmount = 0;
    //If I display a message here, it shows grdItems.Rows.Count is 0
    foreach (GridViewRow row in grdItems.Rows)
    {
        if (row.RowType == DataControlRowType.DataRow)
        {
            CheckBox chkRow = (row.Cells[0].FindControl("chkCtrl") as CheckBox);
            if (chkRow.Checked)
            {
                TotalAmount += Decimal.Parse(row.Cells[2].Text);
            }
        }
    }

    decimal amount;
    if (decimal.TryParse(txtAmount.Text, out amount))
    {
        if (amount > TotalAmount)
        {
            result = false;
        }
    }
    else
    {
        result = false;
    }

    return result;
}

A:

This sounds like a viewstate issue where when the page is posting back to the server, it is losing all the data in the grid. Have you tried enabling viewstate on your page to see if the gridview rows are returned. 

