这是一个棘手的情况,因为您正在处理动态控件,您需要在页面初始化时填充它们以保持视图状态,而且在按钮单击期间添加到更新面板内的控件的事件似乎在下一次回发之前不会被注册,所以正常的按钮单击事件仅在您单击新添加的控件时每隔一次触发一次。除了我的做法之外,可能还有其他方法可以解决这个问题。如果有人知道我想知道。
我的解决方案是保留您动态添加的内容的列表,并将其存储在会话变量中(因为在页面初始化期间未加载视图状态)。然后在页面上初始化加载您之前添加的任何控件。然后在页面加载期间使用一些自定义代码或正常的点击事件来处理点击事件。
我创建了一个示例页面来帮助测试这一点。
这是 aspx 页面 (default.aspx) 的代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!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 id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<p>This only updates on full postbacks: <%= DateTime.Now.ToLongTimeString() %></p>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="PlaceholderControls" runat="server"></asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
这是页面背后代码的代码(default.aspx.cs):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
/// <summary>
/// this is a list for storing the id's of dynamic controls
/// I have to put this in the session because the viewstate is not
/// loaded in the page init where we need to use it
/// </summary>
public List<string> DynamicControls
{
get
{
return (List<string>)Session["DynamicControls"];
}
set
{
Session["DynamicControls"] = value;
}
}
protected void Page_Init(object sender, EventArgs e)
{
PlaceholderControls.Controls.Clear();
//add one button to top that will cause a full postback to test persisting values--
Button btnFullPostback = new Button();
btnFullPostback.Text = "Cause Full Postback";
btnFullPostback.ID = "btnFullPostback";
PlaceholderControls.Controls.Add(btnFullPostback);
PlaceholderControls.Controls.Add(new LiteralControl("<br />"));
PostBackTrigger FullPostbackTrigger = new PostBackTrigger();
FullPostbackTrigger.ControlID = btnFullPostback.ID;
UpdatePanel1.Triggers.Add(FullPostbackTrigger);
//-----------------------------------------------------------------------
if (!IsPostBack)
{
//add the very first control
DynamicControls = new List<string>();
//the DynamicControls list will persist because it is in the session
//the viewstate is not loaded yet
DynamicControls.Add(AddControls(NextControl));
}
else
{
//we have to reload all the previously loaded controls so they
//will have been added to the page before the viewstate loads
//so their values will be persisted
for (int i = 0; i < DynamicControls.Count; i++)
{
AddControls(i);
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
//we have to increment the initial
//control count here here be cause we cannot persit data in the viewstate during
//page init
NextControl++;
}
else
{
HandleAddNextClick();
}
}
/// <summary>
/// this function looks to see if the control which caused the postback was one of our
/// dynamically added buttons, we have to do this because the update panel seems to interefere
/// with the event handler registration.
/// </summary>
private void HandleAddNextClick()
{
//did any of our dynamic controls cause the postback if so then handle the event
if (Request.Form.AllKeys.Any(key => DynamicControls.Contains(key)))
{
DynamicControls.Add(AddControls(NextControl));
NextControl++;
}
}
protected void btnAddNext_Command(object sender, CommandEventArgs e)
{
//this is intentionally left blank we are handling the click in the page load
//because the event for controls added dynamically in the click does
//not get registered until after a postback, so we have to handle it
//manually. I think this has something to do with the update panel, as it works
//when not using an update panel, there may be some other workaround I am not aware of
}
/// <summary>
/// variable for holding the number of the next control to be added
/// </summary>
public int NextControl
{
get
{
return ViewState["NextControl"] == null ? 0 : (int)ViewState["NextControl"];
}
set
{
ViewState["NextControl"] = value;
}
}
/// <summary>
/// this function dynamically adds a text box, and a button to the placeholder
/// it returns the UniqueID of the button, which is later used to find out if the button
/// triggered a postback
/// </summary>
/// <param name="ControlNumber"></param>
/// <returns></returns>
private string AddControls(int ControlNumber)
{
//add textbox
TextBox txtValue = new TextBox();
txtValue.ID = "txtValue" + ControlNumber;
PlaceholderControls.Controls.Add(txtValue);
//add button
Button btnAddNext = new Button();
btnAddNext.Text = "Add Control " + ControlNumber;
btnAddNext.ID = "btnAddNext" + ControlNumber;
int NextControl = ControlNumber + 1;
btnAddNext.CommandArgument = NextControl.ToString();
btnAddNext.Command += new CommandEventHandler(btnAddNext_Command);
PlaceholderControls.Controls.Add(btnAddNext);
//add a line break
PlaceholderControls.Controls.Add(new LiteralControl("<br />"));
return btnAddNext.UniqueID;
}
}
让我知道这段代码是否对您有帮助。我试图根据我对正在发生的事情及其工作方式的理解添加评论。