2011-03-24 92 views
3

我一直用默认的ASP.NET Web应用程序模板玩弄和下面的代码会抛出一个异常:未设置的一个实例 ASP.NET/C#混乱

对象引用目的。

点击创建的按钮。

任何人都可以提供技术解释吗?

注1:标记只是一个带有占位符的空白页 - 见下文。

注2:用Button代替LinkButton,代码不会抛出异常并起作用。

public partial class test : System.Web.UI.Page 
{ 
    protected override void OnInit(EventArgs e) 
    { 
     foo(); 
    } 
    protected override void OnLoad(EventArgs e) 
    { 
     foo(); 
    } 
    protected void foo() 
    { 
     placeholder1.Controls.Clear(); 
     placeholder1.Controls.Add(new Button() { Text = "test", ID = "btn" }); 
    } 
} 

标记:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="test.aspx.cs" Inherits="WebApplication1.test" %> 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head runat="server"> 
</head> 
<body> 
    <form id="form1" runat="server"> 
    <div> 
     <asp:PlaceHolder runat="server" ID="placeholder1" /> 
    </div> 
    </form> 
</body> 
</html> 
+4

什么是例外? – Brandon 2011-03-24 14:43:30

+0

未将对象引用设置为对象的实例。 – maxp 2011-03-24 14:45:33

+1

什么行是抛出的异常? – Oded 2011-03-24 14:46:54

回答

0

看起来要么PLACEHOLDER1或placeholder1.Controls为空。这是给出你的代码示例的NullReferenceException的唯一解释。

0

我的猜测是该按钮一旦从回传回来就为空。你基本上是删除按钮,并创建一个新的按钮,这可能会删除相关的事件。

只是为了支持我的理论联系我尝试这样做:

protected override void OnInit(EventArgs e) 
{ 
    if (!IsPostBack) 
     foo(); 
} 
protected override void OnLoad(EventArgs e) 
{ 
    if (!IsPostBack) 
     foo(); 
} 
protected void foo() 
{ 
    placeholder1.Controls.Clear(); 
    placeholder1.Controls.Add(new Button() { Text = "test", ID = "btn" }); 
} 

并没有收到您收到的错误。

为什么你想像你一样在运行时添加按钮?

+0

你没有收到错误,因为按钮,更不用说事件在回发时不存在了......删除你的'IsPostBack'条件,它会发生。 – maxp 2011-03-24 15:15:57

+0

对,我试过你的代码并收到错误。通过在Init/Load上动态创建按钮,它仅存在于该特定请求中。一旦后发生(即点击按钮)按钮和相关的事件为空,这就是为什么你遇到了对象引用异常,它仍然需要存在于它已经事先做好的状态回发 – 2011-03-24 15:20:41

+0

回发是生命周期的一部分:http://msdn.microsoft.com/en-us/library/ms178472.aspx – maxp 2011-03-24 15:25:00

0

如果您从OnLoad()中删除对foo()的调用,我认为代码将开始工作。

原因是由于页面生命周期中的事件顺序。为了使控件能够引发事件,需要在ProcessPostData(),RaiseChangedEvents()和RaisePostBackEvents()事件发生之前创建控件(参见http://www.eggheadcafe.com/articles/o_aspNet_Page_LifeCycle.jpg以获取页面生命周期的图形表示)。这些事件会在OnInit()之前但OnLoad之前()

由于您的代码现在通过调用OnLoad()中的foo(),您将销毁在OnInit()中调用foo()时创建的实例,因此当Event引发了不再存在的控件,因此“对象引用未设置为实例”消息。