在我看来,在 ASP.NET Web 窗体中动态添加控件存在固有的困难。具体来说,对于要包含在 中的动态添加的控件ViewState
,并使其事件正确连接等等,建议在Page_PreInit
事件期间添加这些控件。
也就是说,很多时候我们可能希望根据事件添加此类控件,例如用户单击按钮。控制特定事件(如 Click 事件)始终在 Init 之后运行,甚至在 Load 之后运行。假设以下 .aspx....
<form id="form1" runat="server">
<div>
<asp:PlaceHolder ID="phAddresses" runat="server"></asp:PlaceHolder>
<br /><br />
<asp:Button ID="btnAddAddress" runat="server" Text="Add Another Address" OnClick="btnAddAddress_Click" />
...以及以下 .aspx.cs ....
private static List<AddressUserControl> addresses = new List<AddressUserControl>();
protected void Page_PreInit(object sender, EventArgs e)
{
foreach (AddressUserControl aCntrl in addresses)
{
phAddresses.Controls.Add(aCntrl);
// Helper to find button within user control
addressButtonControl = findAddressControlRemoveButton(aCntrl);
addressUserControlButton.ID = "btnRemoveAddress" + addressCount;
addressUserControlButton.Click += new EventHandler(addressUserControlButton_Click);
addressCount++;
}
}
protected void btnAddAddress_Click(object sender, EventArgs e)
{
AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx") as AddressUserControl;
addresses.Add(aCntrl);
}
现在在上述情况下,显示的用户控件的数量总是比用户实际添加的数量少一,因为 Click 事件直到 PreInit 之后才会运行,此时控件必须添加到占位符。我必须在这里遗漏一些东西,因为这似乎是 ASP 生命周期所固有的,并且需要一些“hack”或其他。
编辑 - 是的,出于某种原因,我在 btnAddress_Click() 期间添加的 EventHandlers 不会运行,只有我在 Page_Init 期间添加的 EventHandlers 或在标记中以声明方式添加。这就是我试图做的......
protected void btnAddAddress_Click(object sender, EventArgs e)
{
AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx") as AddressUserControl;
addresses.Add(aCntrl);
phAddresses.Controls.Add(aCntrl);
findAddressControlRemoveButton(aCntrl);
addressUserControlButton.ID = "btnRemoveAddress" + addresses.Count;
///////////////////////////////////////////////////////////////////////////////////
// ADDED EVENT HANDLER HERE
//////////////////////////////////////////////////////////////////////////////////////
addressUserControlButton.Click += new E ventHandler(addressUserControlButton_Click);
}
...但事件不会像我所说的那样触发。有任何想法吗?
编辑 - 这是我的 AddressUserControl 的标记。文件背后的代码没有逻辑
<%@ Control Language="C#" ClassName="AddressUserControl" AutoEventWireup="true" CodeBehind="AddressUserControl.ascx.cs" Inherits="XFAWithUserControl.UserControls.AddressUserControl" %>
<asp:Panel ID="pnlAddressForm" runat="server">
<asp:Label ID="lblStreet" runat="server" Text="Street Address"></asp:Label>
<asp:TextBox ID="txtStreet" runat="server"></asp:TextBox>
<br /><br />
<asp:Label ID="lblCity" runat="server" Text="City"></asp:Label>
<asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
<br /><br />
<asp:Label ID="lblState" runat="server" Text="State"></asp:Label>
<asp:TextBox ID="txtState" runat="server"></asp:TextBox>
<br /><br />
<asp:Label ID="lblZip" runat="server" Text="Zip"></asp:Label>
<asp:TextBox ID="txtZip" runat="server"></asp:TextBox>
<br /><br />
<asp:Button ID="btnRemoveAddress" runat="server" Text="Remove Address" />
</asp:Panel>
现在我对 btnRemoveAddress 的点击事件就是这样愚蠢的......
private void addressUserControlButton_Click(object sender, EventArgs e)
{
Button thisButton = sender as Button;
thisButton.Text = "Why Hello";
}
但我的目标是让它删除关联的 AddressUserControl,以便用户可以通过单击按钮从页面中添加和/或删除任意数量的 AddressUserControl。
编辑 - 这是我现在所拥有的,仍然无法正常工作
protected void btnAddAddress_Click(object sender, EventArgs e)
{
AddressUserControl aCntrl = LoadControl("~/UserControls/AddressUserControl.ascx") as AddressUserControl;
addresses.Add(aCntrl);
phAddresses.Controls.Add(aCntrl);
findAddressControlRemoveButton(aCntrl);
addressUserControlButton.ID = "btnRemoveAddress" + addresses.Count;
aCntrl.ChangeText += new EventHandler(addressUserControlButton_Click);
}
private void addressUserControlButton_Click(object sender, EventArgs e)
{
Button thisButton = sender as Button;
thisButton.Text = "Why Hello";
}
地址用户控件.ascx
<asp:Panel ID="pnlAddressForm" runat="server">
<asp:Label ID="lblStreet" runat="server" Text="Street Address"></asp:Label>
<asp:TextBox ID="txtStreet" runat="server"></asp:TextBox>
<br /><br />
<asp:Label ID="lblCity" runat="server" Text="City"></asp:Label>
<asp:TextBox ID="txtCity" runat="server"></asp:TextBox>
<br /><br />
<asp:Label ID="lblState" runat="server" Text="State"></asp:Label>
<asp:TextBox ID="txtState" runat="server"></asp:TextBox>
<br /><br />
<asp:Label ID="lblZip" runat="server" Text="Zip"></asp:Label>
<asp:TextBox ID="txtZip" runat="server"></asp:TextBox>
<br /><br />
<asp:Button ID="btnRemoveAddress" runat="server" Text="Remove Address" OnClick="btnRemoveAddress_Click" />
</asp:Panel>
地址用户控件.ascx.cs
public event EventHandler ChangeText;
protected void Page_Load(object sender, EventArgs e)
{
}
public void btnRemoveAddress_Click(object sender, EventArgs e)
{
if (this.ChangeText != null)
{
ChangeText(sender, e);
}
}