我有2个Gridviews。第一个网格具有一个按钮,当单击该按钮时,它将根据被单击的按钮的ID向第二个网格填充数据。

然后,我在RowDataBound函数中有代码来显示基于所选行的网格。但是问题是代码在填充函数之前自动运行RowDataBound。因此,第二个网格不显示。

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>

后面的代码:
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";
            }
        }
    }
}

选择按钮的代码:
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 ();");
}

所以问题是当我单击网格中的“选择”按钮时,它先运行RowDataBound,然后再运行gridviewParent_SelectedIndexChanged,但是我需要先运行gridviewParent_SelectedIndexChanged。我可以从RowDataBound调用gridviewParent_SelectedIndexChanged函数吗?

Page_Load函数:
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();

            }
        }
    }

最佳答案

仅当已调用OnRowDataBoundDataBind方法时,才调用GridView事件。

在您的特定情况下,问题出在Page_Load条件的else分支中的Page.IsPostBack中:

 else
{
    if (ViewState["ParentID"] != null)
    {
        ParentID = (int?)ViewState["ParentID"];
        List<lookupCVRT> work = ViewState["CVRT"] as List<lookupCVRT>;
        gvCVRT.DataSource = work;
        gvCVRT.DataBind();

    }
}

每次回发都会运行此代码。除非您在代码中的其他位置重置ViewState["ParentID"],否则在每次回发时,都将再次绑定(bind)GridView gvCVRT。这就是调用RowDataBound的原因。完成Page_Load后,页面将调用其他事件处理程序,在您的情况下为gridviewParent_SelectedIndexChanged

为了解决此问题,您需要更改Page_Load处理程序中的代码,以便不存在对DataBind的回发调用:
// 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>;
        }
    }
}

问题的根本原因是您需要回发请求中的数据,并且将它们放入ViewState["CVRT"]中,而不是重新请求数据。在Web应用程序中,很常见的是再次读取数据以获取新请求。因此,您可能会考虑是否真的需要将数据放入ViewState或是否可以在从数据源回发时请求它们。

将数据放入ViewState会增加传输到客户端的页面的大小(基本上,您具有GridView的HTML,此外,您还在ViewState中拥有数据)。因此,在大多数情况下,重新请求它们是更好的方法。

08-16 05:14