我正在处理一个用户表单,其中我想动态生成与用户想要的一样多的辅助电话字段(在按钮点击事件上)。我在此页面上关注了Daniel的动态控件实例化: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
}
请注意,我添加了最后一行:
Session [“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方法的这一行抛出一个Null引用异常(对象引用未设置为对象的实例):
phonePnl.Controls.Add(controlToAdd);
在调试中我注意到,在第一次单击按钮时,在我的phoneBtn_Click方法中,controlToAdd.Application,controlToAdd.Cache等也会抛出Null Reference Exceptions,但它仍会生成控件并返回页面。它还将控件及其ID添加到词典中。
然后在第二次单击按钮时,在它到达导致异常的行之前,我的phonePnl变量为null。我可以推测这是造成异常的原因,但为什么我的phonePnl变量在这种情况下是null,而不是在第二次OnInit调用/第一次回发?
我一整天都在反对这一点,我希望有人可以提供一些见解。
答案 0 :(得分:0)
而不是controlToAdd.LoadControl
使用Page.LoadControl
并查看是否有效