开发者

ASP.NET / C# confusion over dynamically created controls

开发者 https://www.devze.com 2023-02-19 17:55 出处:网络
Ive been playing around with the default ASP.NET web application template and the following code throws an exception:

Ive been playing around with the default ASP.NET web application template and the following code throws an exception:

Object reference not set to an instance of an object.

when clicking the created button.

Can anyone offer a technical explanation?

Note 1: The markup is just a blank page with a placeholder in it - see below.

Note 2: Substituting Button for LinkButton, and the code does not throw an exception and works.

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" });
    }
}

Markup:

<%@ Page Language="C#" AutoEv开发者_JS百科entWireup="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>


It looks like either placeholder1 or placeholder1.Controls is null. This is the only explanation for a NullReferenceException given your code example.


My guess would be that the button is null once it comes back from the post-back. You are essentially removing the Button and creating a new button which will likely remove the associated event.

Just to support my thoery I tried this:

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" });
}

and did not receive the error that you received.

Why are you wanting to add the button at run-time like you are?


If you remove the call to foo() from the OnLoad() I think the code will start to work.

The reason for this is due to the order of events in the Page Life cycle. In order for a control to be able to raise events the control needs to have been created before the ProcessPostData(), RaiseChangedEvents() and RaisePostBackEvents() events occur (see http://www.eggheadcafe.com/articles/o_aspNet_Page_LifeCycle.jpg for a graphical representation of the page lifecycle) These events are raises after OnInit() but before OnLoad()

As your code stands at the moment by calling foo() in OnLoad(), you destroy the instance created when foo() was called in OnInit() and so when the Event is raised the control that raised it no longer exists, hence the "Object reference not set to an instance" message.

0

精彩评论

暂无评论...
验证码 换一张
取 消