b3ns b3ns - 3 months ago 32
ASP.NET (C#) Question

GridView in LoginView giving wrong row count

I have a GridView within a LoginView that I am getting an Index Out Of Range error with. When I display the # of rows in the GridView it always shows 0 which is causing this error.


Is there something specific that I need to be doing to get a GridView
to properly work within a LoginView?


Below is the code that is being run when I click on a button in the GridView and the error only comes up on the GridView
row = gv.Rows[e.RowIndex];
line. If I use only
e.RowIndex
I do not get the error and it will actually return the proper number. If I do gv.DataKeys.Count it will return the correct count. If I do
gv.Rows.Count
it will always be 0. I think it has something to do with a PostBack because if I do a row count in my
page_load
then it returns the correct count. Please let me know if there is anything else that you need for me to post?

protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
try
{
GridView gv = ReviewLoginView.FindControl("gvReview") as GridView;
GridViewRow row = gv.Rows[e.RowIndex];

string Id = (row.FindControl("lblID") as Label).Text;

string constr = System.Configuration.ConfigurationManager.AppSettings["ObservationCardCS"];
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand("cardReview"))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@id", Id);

cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();
}
}
gv.EditIndex = -1;
this.BindGrid();

}
catch (Exception ex)
{

GridView gv = ReviewLoginView.FindControl("gvReview") as GridView;

int index = e.RowIndex;

lblError.ForeColor = System.Drawing.Color.Red;
lblError.Text = ex.Message + " " + index.ToString() + " " + gv.Rows.Count;
}
}


Below is the LoginView from the aspx page.

<asp:LoginView runat="server" ViewStateMode="Disabled" ID="ReviewLoginView">
<LoggedInTemplate>
<%--<AnonymousTemplate>--%>
<div>
<asp:GridView ID="gvReview" runat="server" AutoGenerateColumns="false" DataKeyNames="ID"
OnRowDataBound="OnRowDataBound" OnRowDeleting="OnRowDeleting" EnableViewState="true"
EmptyDataText="No records have been added." AllowSorting="true" ShowHeaderWhenEmpty="true"
AlternatingRowStyle-BackColor="#e0e0e0" HeaderStyle-BackColor="#d0d0d0" ViewStateMode="Disabled"
EnableSortingAndPagingCallbacks="false">
<Columns>
<asp:TemplateField HeaderText="ID" ShowHeader="false" Visible="true">
<ItemTemplate>
<asp:Label ID="lblID" runat="server" Text='<%# Bind("ID") %>' CssClass="cmsID"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="User">
<ItemTemplate>
<asp:Label ID="lblSubmittedBy" runat="server" Text='<%# Eval("submittedBy") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Location">
<ItemTemplate>
<asp:Label ID="lblLocation" runat="server" Text='<%# Eval("location") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Date">
<ItemTemplate>
<asp:Label ID="lblSubmittedDate" runat="server" Text='<%# Eval("submittedDate") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="What Was Observed?">
<ItemTemplate>
<asp:Label ID="lblWhatWasObserved" runat="server" Text='<%# Eval("whatWasObserved") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="What Action Was Taken?">
<ItemTemplate>
<asp:Label ID="lblWhatActionWasTaken" runat="server" Text='<%# Eval("whatActionWasTaken") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="What Agreement Was Reached?">
<ItemTemplate>
<asp:Label ID="lblWhatAgreementWasReached" runat="server" Text='<%# Eval("whatAgreementWasReached") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Edit">
<ItemTemplate>
<asp:Button ID="btnSubmit" runat="server" Text="Edit" CssClass="editbutton" />
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField HeaderText="Review" ButtonType="Button" ShowDeleteButton="true" DeleteText="Review" />
</Columns>
</asp:GridView>
</div>
</LoggedInTemplate>
<%--</AnonymousTemplate>--%>
<AnonymousTemplate>
You must login to view submitted Observation Cards.
</AnonymousTemplate>
</asp:LoginView>


Below is the BindGrid()

private void BindGrid()
{
try
{
SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.AppSettings["ObservationCardCS"]);
{
SqlCommand comm = new SqlCommand("cardSelectNew2", conn);
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = comm;
comm.CommandType = CommandType.StoredProcedure;
comm.Parameters.AddWithValue("@Begin", "1/1/1950");
comm.Parameters.AddWithValue("@End", "12/31/2049");
comm.Parameters.AddWithValue("@Reviewed", "0");
comm.Parameters.AddWithValue("@OrderBy", "CH.id");
comm.Parameters.AddWithValue("@AscDesc", "Asc");
comm.Parameters.AddWithValue("@DateRange", "Last 30 Days");

comm.Connection = conn;
sda.SelectCommand = comm;

DataTable dt = new DataTable();
sda.Fill(dt);

GridView gv = ReviewLoginView.FindControl("gvReview") as GridView;

gv.DataSource = dt;
gv.DataBind();

}
}
catch (Exception ex)
{
lblError.ForeColor = System.Drawing.Color.Red;
lblError.Text = ex.Message;
}
}


Below is my page_load

protected void Page_Load(object sender, EventArgs e)
{

if (!this.IsPostBack)
{
this.BindGrid();
lblError.ForeColor = System.Drawing.Color.Black;
lblError.Text = "";
}

}

Answer

You are on the right track! But without seeing the whole class and markup we can only speculate.

Check that you are not clearing or rebuilding the data on the page load event handler, if the Grid and datasource is defined in the markup then it should cache or requery the data between page postbacks, check that you have set EnableRowCache on the GridView so that you dont have to re-query for the data during postbacks.

It looks like you are using the #OldSchool BindGrid() data load pattern, perhaps the simplest solution may be to ensure that the data is loaded first by calling BindGrid before you try to access the rows:

protected void OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
    this.BindGrid();
    try
    {
... delete logic
        this.BindGrid(); // re-load after the change
    }
    catch (Exception ex)
    {
...
    }
}

Without enabling the row cache though you have to ensure that the same data is loaded into the grid in the same order or delete logic like this based on row index (instead of the primary key of the row) could result in you deleting the wrong data row.

Comments