回发后GridView事件意外引发

时间:2011-08-30 04:57:09

标签: asp.net gridview

考虑一下这个Asp.net页面代码:

<head runat="server">
<title></title>
<script type="text/javascript">
        function showhide(master, detail) {
            var src = $(master).children()[0].src;
            if (src.endsWith("plus.png"))
                src = src.replace('plus.png', 'minus.png');
            else
                src = src.replace('minus.png', 'plus.png');

            $(master).children()[0].src = src;

            $(detail).slideToggle("normal");
        }
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
    <Scripts>
        <asp:ScriptReference Path="~/scripts/jquery-1.6.2.min.js" ScriptMode="Release" />
    </Scripts>
</asp:ScriptManager>
<div>
<asp:SqlDataSource ID="sqlDsCustomers" runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>"
    SelectCommand="SELECT [Customers].[CustomerID], [Customers].[CompanyName], COUNT([OrderID]) TotalOrders&#13;&#10;FROM [Customers] INNER JOIN [Orders] ON [Customers].[CustomerID]=[Orders].[CustomerID]&#13;&#10;Group By [Customers].[CustomerID], [Customers].[CompanyName]">
</asp:SqlDataSource>
    <asp:GridView Width="100%" AllowPaging="True" ID="gvCustomers" AutoGenerateColumns="False"
        DataSourceID="sqlDsCustomers" runat="server" ShowHeader="False" OnRowCreated="gvCustomers_RowCreated">
        <Columns>
            <asp:TemplateField>
                <ItemTemplate>
                    <div class="group" id='<%#String.Format("customer{0}",Container.DataItemIndex) %>'
                        onclick='showhide(<%#String.Format("\"#customer{0}\"",Container.DataItemIndex) %>,<%#String.Format("\"#order{0}\"",Container.DataItemIndex) %>)'>
                        <asp:Image ID="imgCollapsible" CssClass="first" ImageUrl="~/Assets/img/plus.png"
                            Style="margin-right: 5px;" runat="server" /><span class="header">
                                <%#Eval("CustomerID")%>
                                :
                                <%#Eval("CompanyName")%>
                                (<%#Eval("TotalOrders")%>Orders) </span>
                    </div>
                    <div id='<%#String.Format("order{0}",Container.DataItemIndex) %>' class="order">
                        <asp:GridView AutoGenerateColumns="false" CssClass="grid" ID="ddd" runat="server"
                            ShowHeader="true" EnableViewState="false">
                            <RowStyle CssClass="row" />
                            <AlternatingRowStyle CssClass="altrow" />
                            <Columns>
                                <asp:TemplateField ItemStyle-CssClass="rownum">
                                    <ItemTemplate>
                                        <%# Container.DataItemIndex + 1 %>
                                    </ItemTemplate>
                                </asp:TemplateField>
                                <asp:BoundField HeaderText="Order ID" DataField="OrderID" ItemStyle-Width="80px" />
                                <asp:BoundField HeaderText="Date Ordered" DataField="OrderDate" DataFormatString="{0:MM/dd/yyyy}"
                                    ItemStyle-Width="100px" />
                                <asp:BoundField HeaderText="Date Required" DataField="RequiredDate" DataFormatString="{0:MM/dd/yyyy}"
                                    ItemStyle-Width="110px" />
                                <asp:BoundField HeaderText="Freight" DataField="Freight" DataFormatString="{0:c}"
                                    ItemStyle-Width="50px" ItemStyle-HorizontalAlign="Right" />
                                <asp:BoundField HeaderText="Date Shipped" DataField="ShippedDate" DataFormatString="{0:MM/dd/yyyy}"
                                    ItemStyle-Width="100px" />
                            </Columns>
                        </asp:GridView>
                    </div>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</div>
<asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Button" />
</form>

和背后的代码:

protected void Page_Load(object sender, EventArgs e)
{

}
protected void gvCustomers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        string custID = ((DataRowView)e.Row.DataItem)["CustomerID"].ToString();
        using (DataClassesDataContext dc=new DataClassesDataContext())
        {
            List<Order> ord = (from o in dc.Orders
                               where o.CustomerID == custID.Trim()
                               select o).ToList();


            GridView ctrl = e.Row.FindControl("ddd") as GridView;
            ctrl.DataSource = ord;
        }
    }
}
protected void Button1_Click(object sender, EventArgs e)
{
    Response.Redirect("Default.aspx");
}

问题是当我点击Button1重定向到另一个页面gvCustomers_RowCreated加注并且我得到Null引用错误。为什么在回发后引发此事件?


编辑1):

我删除了SqlDataSource并在后面的代码中绑定了GridView,如下所示:

public partial class Default2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        using (DataClassesDataContext dc=new DataClassesDataContext())
        {
            var query = dc.ExecuteQuery<clsRetern>("SELECT [Customers].[CustomerID], [Customers].[CompanyName], COUNT([OrderID]) TotalOrders FROM [Customers] INNER JOIN [Orders] ON [Customers].[CustomerID]=[Orders].[CustomerID] Group By [Customers].[CustomerID], [Customers].[CompanyName]").ToList();

            List<clsRetern> ret = new List<clsRetern>();
            foreach (var item in query)
            {
                clsRetern r = new clsRetern();
                r.CompanyName = item.CompanyName;
                r.CustomerID = item.CustomerID;
                r.TotalOrders = item.TotalOrders;

                ret.Add(r);
            }

            gvCustomers.DataSource = ret;
            gvCustomers.DataBind();        
        }
    }
}
protected void gvCustomers_RowCreated(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        string custID = ((clsRetern)e.Row.DataItem).CustomerID.Trim();
        using (DataClassesDataContext dc=new DataClassesDataContext())
        {
            List<Order> ord = (from o in dc.Orders
                               where o.CustomerID == custID.Trim()
                               select o).ToList();


            GridView ctrl = e.Row.FindControl("ddd") as GridView;
            ctrl.DataSource = ord;
        }
    }
}
protected void Button1_Click(object sender, EventArgs e)
{
    Response.Redirect("Default.aspx",true);
}
}

public class clsRetern
{
    public string CustomerID { get; set; }
    public string CompanyName { get; set; }
   public int TotalOrders { get; set; }
}

我尝试Response.Redirect("Default.aspx");,但问题仍然存在。

3 个答案:

答案 0 :(得分:2)

如果你理解ASP.NET页面模型,那么这个问题不应该出现在你面前。每次请求进入ASP.NET页面时,都会创建一个新的页面对象以及整个控制树,并在回发后的场景中使用视图状态管理状态。因此,在您的情况下,每当发生回发时,都会创建一个新页面和网格视图。 gid-view的数据将保存在视图状态中,网格将绑定到该数据。

无论是否显式调用RowCreated,每当创建网格行时都会引发DataBind事件。事件的目的是使用户可以调整UI(网格视图单元格) - 例如如果需要,可以将一些控件推入网格视图单元格。无论后期情况如何,都应该发生同样的情况,否则这些动态控件将无法创建。通常,这些控件将使用视图状态恢复其状态,并使您的网格视图UI(控制树)恢复到第一页循环中。

答案 1 :(得分:0)

多数民众赞成因为即使您解雇了Response.Redirect,仍会引发Page_Load事件,如果您的GridView绑定代码不在!IsPostBack内,则该代码将被点击

试试这个。

protected void Page_Load(object sender, EventArgs e)
{
    try
    {
        if (!IsPostBack)
        {
            //bind gridview here
        }
    }
    catch (Exception exception)
    {
        //Elmah.ErrorSignal.FromCurrentContext().Raise(exception);
    }
}

精明?

答案 2 :(得分:0)

将EnableViewState = False添加到页面指令,以防止在每个帖子上运行“RowCreated”。