【问题标题】:Null Reference Exception for dynamic ascx User Control动态 ascx 用户控件的空引用异常
【发布时间】:2012-07-11 08:37:42
【问题描述】:

我正在处理一个用户表单,我希望在其中动态生成用户想要的任意数量的辅助电话字段(在按钮单击事件上)。我在这个页面上关注了丹尼尔的动态控件实例化:How can I re-instantiate dynamic ASP.NET user controls without using a database?

我也在这个页面实现了lordscarlet提出的“事件冒泡”解决方案:Eventhandling in ascx usercontrols

我的 user.aspx 页面的相关部分:

<asp:Panel ID="phonePnl" runat="server"></asp:Panel>
            <tr><td><asp:Button ID="phoneBtn" Text="Add Secondary Phone" OnClick="phoneBtn_Click" runat="server" /></td></tr>

user.aspx.cs CodeBehind 的相关部分

    // ============================================================================
protected void phoneBtn_Click(object sender, EventArgs e)
{
    UserControl controlToAdd = new UserControl();
    controlToAdd = (UserControl)controlToAdd.LoadControl("~/DynamicData/FieldTemplates/SecondaryPhone.ascx");

    controlToAdd.ID = Guid.NewGuid().ToString();

    Panel phonePnl = (Panel)fvUser.FindControl("phonePnl");

    Literal lit = new Literal();
    lit.Text = "<tr><td>Secondary Phone</td><td>";
    phonePnl.Controls.Add(lit);
    phonePnl.Controls.Add(controlToAdd);
    lit = new Literal();
    lit.Text = "</td></tr>";
    phonePnl.Controls.Add(lit);

    myControlList.Add(controlToAdd.ID, controlToAdd.AppRelativeVirtualPath);
    Session["myControlList"] = myControlList;
}

// ============================================================================
protected override void OnInit(EventArgs e)
{
    InitializeComponent();
    if (!IsPostBack)
    {
        myControlList = new Dictionary<string, string>();
        Session["myControlList"] = myControlList;
    }
    else
    {
        myControlList = (Dictionary<string, string>)Session["myControlList"];

        foreach (var registeredControlId in myControlList.Keys)
        {
            UserControl controlToAdd = new UserControl();
            controlToAdd = (UserControl)controlToAdd.LoadControl(myControlList[registeredControlId]);
            Panel phonePnl = new Panel();
            phonePnl = (Panel)fvUser.FindControl("phonePnl");
            phonePnl.Controls.Add(controlToAdd);
        }
    }
    base.OnInit(e);
}

// ============================================================================
private void InitializeComponent()
{
    this.Load += new System.EventHandler(this.Page_Load);
    SecondaryPhoneControl.BubbleClick += new EventHandler(admin_user_BubbleClick);
}

// ============================================================================
private void admin_user_BubbleClick(object sender, EventArgs e)
{
    //todo
}

请注意,我已添加最后一行:
会话["myControlList"] = myControlList;

另外,fvUser 只是我在 user.aspx 页面中的 FormView ID。

虽然它不在 Daniel 的解决方案中,但我的想法是,对于您添加的每个控件,您都需要将其添加到您的 Dictionary 中。我在这方面完全被误导了吗?

我的用户控件是一个带有 TextBox 和 Button 的 ascx(用于删除控件,如果用户决定不想要该字段)。请注意,此删除操作尚未真正实现,但在此问题解决后,事件存在于我的父代码隐藏中。

SecondaryPhone.ascx

<%@ Control Language="C#" CodeBehind="SecondaryPhone.ascx.cs" Inherits="TwentyFourSeven.DynamicData.FieldTemplates.SecondaryPhone" %>

SecondaryPhone.ascx.cs

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;
using System.Web.DynamicData;

namespace TwentyFourSeven.DynamicData.FieldTemplates

{
public partial class SecondaryPhone : System.Web.UI.UserControl
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    public void SetPhone(String phone)
    {
        secPhoneTxt.Text = phone;
    }

    protected override void LoadViewState(object savedState)
    {
        base.LoadViewState(savedState);
        secPhoneTxt.Text = (String)ViewState["secPhoneTxt"];
    }

    protected override object SaveViewState()
    {
        ViewState["secPhoneTxt"] = secPhoneTxt.Text;
        return base.SaveViewState();
    }

    private void secPhoneBtn_Click(object sender, EventArgs e)
    {
    }

    public event EventHandler BubbleClick;

    protected void OnBubbleClick(EventArgs e)
    {
        if (BubbleClick != null)
        {
            BubbleClick(this, e);
        }
    }

    protected override void OnInit(EventArgs e)
    {
        InitializeComponent();
        base.OnInit(e);
    }

    private void InitializeComponent()
    {
        this.secPhoneBtn.Click += new System.EventHandler(this.secPhoneBtn_Click);
        this.Load += new System.EventHandler(this.Page_Load);
    }
}
}

调试时,第一次加载页面时,OnInit 正常工作,单击“添加辅助电话”按钮在第一次单击时工作。第二次单击在我的 OnInit 方法的这一行上引发空引用异常(对象引用未设置为对象的实例):

phonePnl.Controls.Add(controlToAdd);

在调试中我注意到第一次点击按钮时,在我的phoneBtn_Click方法中,controlToAdd.Application、controlToAdd.Cache等也会抛出空引用异常,但它仍然会生成控件并返回页面。它还将控件及其 ID 添加到字典中。

然后在第二次单击按钮时,就在它碰到导致异常的行之前,我的 phonePnl 变量为空。我可以推测这是导致异常的原因,但为什么我的 phonePnl 变量在这种情况下为 null,而不是在第二次 OnInit 调用/第一次回发中?

我整天都在努力解决这个问题,我希望有人能提供一些见解。

【问题讨论】:

    标签: c# webforms nullreferenceexception dynamic-controls


    【解决方案1】:

    Page.LoadControl 代替controlToAdd.LoadControl 看看是否可行

    【讨论】:

    • 发生同样的异常 - 引用 Page LoadControl 与特定控件的 LoadControl 有区别吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2010-11-20
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    相关资源
    最近更新 更多