ASP.NET / C# 对动态创建的控件的混淆

发布于 2024-10-25 19:24:02 字数 1202 浏览 1 评论 0原文

我一直在使用默认的 ASP.NET Web 应用程序模板,以下代码抛出异常:

对象引用未设置为 对象的实例。

单击创建的按钮时。

谁能提供技术解释?

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

注2:用Button替换LinkBut​​ton,代码不会抛出异常并且可以工作。

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>

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#" 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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深海不蓝 2024-11-01 19:24:02

看起来 placeholder1 或 placeholder1.Controls 为空。这是给定代码示例的 NullReferenceException 的唯一解释。

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

久夏青 2024-11-01 19:24:02

我的猜测是,一旦按钮从回发返回,它就为空。您实质上是删除按钮并创建一个新按钮,这可能会删除关联的事件。

只是为了支持我的理论,我尝试了以下操作:

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

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

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

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?

橘亓 2024-11-01 19:24:02

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文