![](/img/trans.png)
[英]Asp.Net: dynamically created controls stop working after first PostBack
[英]ASP.NET dynamically created controls and Postback
我知道这个问题已经被问了好几千次了,之前我一直在努力,但由于某种原因,我无法完成我想要完成的任务......我有一个动态添加的LinkButton,点击时会动态添加控件(在此示例中为文本框)指向同一面板。 目的是在点击LinkButton时连续添加任意数量的控件(即我单击一次,一个框,然后另一次单击将给我2个框,另一个单击添加第三个)。 在下面的代码中,我使用序列化的当前日期和时间为每个文本框控件创建唯一的ID。
当我执行代码时,单击“添加过滤器”将生成一个新的文本框,但一旦再次单击将创建一个新文本框,并处理它之前的文本框。 相反,我想要保留以前的文本框以及在其中提交的任何数据。
非常感谢您的帮助。
在aspx中:
<asp:Panel ID="pnlFilter" runat="server">
</asp:Panel>
在aspx.cs中:
protected void Page_Init(object sender, EventArgs e)
{
LinkButton lb = new LinkButton();
lb.ID = "lbAddFilter";
pnlFilter.Controls.Add(lb);
lb.Text = "Add Filter";
lb.Click += new EventHandler(lbAddFilter_Click);
}
void lbAddFilter_Click(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.ID = "tb" + DateTime.Now.ToBinary().ToString();
pnlFilter.Controls.Add(tb);
}
对于其他试图做这样事情的人:不要。 相反,要考虑信息流,并了解有更好的方法。 输入控件不需要动态创建。 它们可以是静态的,在填写和提交时,该信息必须在某处(例如,数据库,缓存,会话)。 一旦它在那里,在回发时,循环选择存储中的所有项目并为它们创建显示。
这就是我所做的,它让生活变得更轻松。 希望它可以帮助某人。
void lbAddFilter_Click(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.ID = "tb" + DateTime.Now.ToBinary().ToString();
pnlFilter.Controls.Add(tb);
}
这不会起作用 - 这是你在问题中推断的生命周期问题。 有很多方法可以解决这个问题,但Honus Wagner的建议是最灵活的。
这里发生的是你在事件处理程序中调用Controls.Add并且控件被添加到控件列表中,并且在下一个请求(无论是部分回发,完全回发还是新页面命中)上,该控件因为你没有把它坚持到任何地方而消失了。
以下是您的页面事件生命周期中正在发生的事情:
我不确定这是最好的做法,但我已经成功使用了类似于此的模型(注意我没有测试过这段代码 - 可能需要调整):
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
LinkButton lb = new LinkButton();
lb.ID = "lbAddFilter";
pnlFilter.Controls.Add(lb);
lb.Text = "Add Filter";
lb.Click += new EventHandler(lbAddFilter_Click);
// regenerate dynamically created controls
foreach ( var control in PersistedControls )
{
pnlFilter.Controls.Add(GenerateControl(control));
}
}
private IList<Control> _persistedControls;
private const string PersistedControlsSessionKey = "thispage_persistedcontrols";
private IList<Control> PersistedControls
{
if (_persistedControls == null)
{
if (Session[PersistedControlsSessionKey] == null)
Session[PersistedControlsSessionKey] = new List<Control>();
_persistedControls = Session[PersistedControlsSessionKey] as IList<Control>;
}
return _persistedControls;
}
void lbAddFilter_Click(object sender, EventArgs e)
{
TextBox tb = new TextBox();
tb.ID = "tb" + DateTime.Now.ToBinary().ToString();
PersistedControls.Add(tb);
pnlFilter.Controls.Add(tb);
}
请注意,我不确定是否将实际的Control对象添加到会话存储中 - 我相信控件ID存在问题会导致回发错误(可能是Control不可序列化?)。 在我开发的解决方案中,我在GenerateControl方法中生成了一个新的TextBox / Label / ComboBox / etc,并在PersistedControls集合中存储了一个自定义容器类,其中包含我需要生成的UI控件的各种属性它在每个页面Init。
我相信你需要在每次回发时重新创建每个控件。
我知道Repeater控件存储有关其子节点的足够信息,以便在数据绑定时重新创建它们...您可以使用它来节省一些工作。
尝试添加,
if(!Page.IsPostback)
--- your code that adds different controls.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.