I have a 2 Gridviews. The first grid has a button that when clicked it will populate a second grid with the data based on the id of the button clicked.
I then have code in the RowDataBound function to show the grid based on the row selected. But the problem is the code is automatically running the RowDataBound before the populate function. So the second grid isn't displaying.
Code for GridView:
<asp:GridView style="width:75%"
ID="gvCVRT"
ShowHeaderWhenEmpty="true"
CssClass="tblResults"
runat="server"
OnRowDataBound="gvCVRT_RowDataBound"
OnSelectedIndexChanged="gridviewParent_SelectedIndexChanged"
DataKeyField="ID"
DataKeyNames="ChecklistID"
AutoGenerateColumns="false"
allowpaging="false"
AlternatingRowStyle-BackColor="#EEEEEE">
<HeaderStyle CssClass="tblResultsHeader" />
<Columns>
<asp:BoundField DataField="ChecklistID" HeaderText="ID" ></asp:BoundField>
<asp:CommandField ShowSelectButton="True" HeaderText="Select" />
<asp:BoundField DataField="ChecklistDate" HeaderText="Checklist Date" dataformatstring="{0:dd/MM/yyyy}"></asp:BoundField>
<asp:BoundField DataField="User" HeaderText="User" ></asp:BoundField>
<asp:BoundField DataField="Note" HeaderText="Note" ></asp:BoundField>
</Columns>
</asp:GridView>
Code behind:
protected void gvCVRT_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
lookupCVRT work = (lookupCVRT)e.Row.DataItem;
GridView gv = sender as GridView;
if (work.ID != null)
{
int index = gv.Columns.HeaderIndex("Select");
if (index > -1)
{
e.Row.Cells[index].Attributes.Add("class", "gvCVRTRow");
e.Row.Cells[index].ToolTip = "Click here to Edit Checklist";
}
}
}
}
Code for select button:
protected void gridviewParent_SelectedIndexChanged(object sender, EventArgs e)
{
List<lookupCVRT> workDetails = lookupCVRT.GetChecklistItemsByChecklistID(Company.Current.CompanyID, ParentID.ToString(), gvCVRT.SelectedDataKey.Value.ToString());
gvCVRTDetails.DataSource = workDetails;
gvCVRTDetails.DataBind();
FireJavascriptCallback("setArgAndPostBack ();");
}
So the problem is when I click on the Select button in the grid it runs the RowDataBound
first then the gridviewParent_SelectedIndexChanged
but I need to run gridviewParent_SelectedIndexChanged
first. Can I call the RowDataBound
function from gridviewParent_SelectedIndexChanged
?
Page_Load function:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
GetChecklistID = "";
if (ParentID.HasValue)
{
ViewState["ParentID"] = ParentID;
List<lookupCVRT> work = lookupCVRT.GetCVRTItems(Company.Current.CompanyID, ParentID.ToString());
ViewState["CVRT"] = work;
gvCVRT.DataSource = work;
gvCVRT.DataBind();
}
}
else
{
if (ViewState["ParentID"] != null)
{
ParentID = (int?)ViewState["ParentID"];
List<lookupCVRT> work = ViewState["CVRT"] as List<lookupCVRT>;
gvCVRT.DataSource = work;
gvCVRT.DataBind();
}
}
}
The OnRowDataBound
event is only called if the DataBind
method for the GridView
has been called.
In your specific case, the problem is in Page_Load
in the else
branch of the Page.IsPostBack
condition:
else
{
if (ViewState["ParentID"] != null)
{
ParentID = (int?)ViewState["ParentID"];
List<lookupCVRT> work = ViewState["CVRT"] as List<lookupCVRT>;
gvCVRT.DataSource = work;
gvCVRT.DataBind();
}
}
This code is run for each postback. Unless you reset ViewState["ParentID"]
somewhere else in your code, on every postback you bind the GridView gvCVRT
again. This is the reason that RowDataBound
is called. After finishing Page_Load
, the page calls the additional event handlers, in your case gridviewParent_SelectedIndexChanged
.
In order to solve this problem, you need to change the code in your Page_Load
handler so that there are no calls to DataBind
for a postback:
// field moved to class level so that you can access this variable instead of a DataRow in gvCVRT
private List<lookupCVRT> work;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
GetChecklistID = "";
if (ParentID.HasValue)
{
ViewState["ParentID"] = ParentID;
work = lookupCVRT.GetCVRTItems(Company.Current.CompanyID, ParentID.ToString());
ViewState["CVRT"] = work;
gvCVRT.DataSource = work;
gvCVRT.DataBind();
}
}
else
{
if (ViewState["ParentID"] != null)
{
ParentID = (int?)ViewState["ParentID"];
work = ViewState["CVRT"] as List<lookupCVRT>;
}
}
}
The root cause of your problem is that you need the data in a postback request and that you put these into ViewState["CVRT"]
instead of requesting the data anew. In web applications it is pretty common the read the data again for a new request. So you might think about whether you really need to put the data into ViewState or whether you can request them upon a postback from the data source.
Putting the data into ViewState increases the size of the page that is transferred to the client (basically you have the HTML for the GridView and in addition you have the data in ViewState). So requesting them anew would be the better way in most cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With