ASP.NET动态创建控件和回发

ASP.NET动态创建控件和回发,asp.net,postback,dynamic-data,Asp.net,Postback,Dynamic Data,我知道这个问题已经被问了几千次了,我以前也一直在努力解决这个问题,但由于某种原因,我无法完成我想完成的事情。。。我有一个动态添加的LinkButton,当单击它时,它将动态地向同一面板添加一个控件(在本例中是一个文本框)。其目的是在单击链接按钮时不断添加尽可能多的控件(即,我单击一次,一个框,然后再单击一次将显示两个框,再单击一次将显示第三个框)。在下面的代码中,我使用序列化的当前日期和时间为每个textbox控件创建一个唯一的ID 当我执行代码时,单击“添加过滤器”将生成一个新的文本框,但再次

我知道这个问题已经被问了几千次了,我以前也一直在努力解决这个问题,但由于某种原因,我无法完成我想完成的事情。。。我有一个动态添加的LinkButton,当单击它时,它将动态地向同一面板添加一个控件(在本例中是一个文本框)。其目的是在单击链接按钮时不断添加尽可能多的控件(即,我单击一次,一个框,然后再单击一次将显示两个框,再单击一次将显示第三个框)。在下面的代码中,我使用序列化的当前日期和时间为每个textbox控件创建一个唯一的ID

当我执行代码时,单击“添加过滤器”将生成一个新的文本框,但再次单击将创建一个新的文本框,并处理它之前的文本框。相反,我希望保留前面的文本框以及其中提交的任何数据

谢谢你的帮助

在aspx中:

<asp:Panel ID="pnlFilter" runat="server">

</asp:Panel>
试着加上

if(!Page.IsPostback)
  --- your code that adds different controls.

我相信您需要在每次回发上重新创建每个控件


我知道Repeater控件存储了足够的关于其子控件的信息,以便在数据绑定时重新创建它们。。。你可以用它来节省一点工作量。

对于任何试图这样做的人:不要。相反,想想信息流,并理解有更好的方法来实现它。不需要动态创建输入控件。它们可以是静态的,在填写和提交一个时,这些信息必须放在某个地方(例如数据库、缓存、会话)。一旦到了那里,在回发时,循环选择存储中的所有项目,并为它们创建一个显示

这就是我所做的,它让生活变得更加轻松。希望它能帮助别人

void lbAddFilter_Click(object sender, EventArgs e)
{
    TextBox tb = new TextBox();
    tb.ID = "tb" + DateTime.Now.ToBinary().ToString();
    pnlFilter.Controls.Add(tb);
}
这是行不通的——正如您在问题中所推断的,这是一个生命周期问题。有很多方法可以解决这个问题,但Honus Wagner的建议是最灵活的

这里发生的情况是您正在调用控件。添加事件处理程序,控件将被添加到控件列表中,在下一个请求中(无论是部分回发、完全回发还是新页面点击),该控件将消失,因为您没有将其保留在任何位置

以下是当前页面事件生命周期中发生的情况:

  • Page调用OnInit并添加链接按钮
  • 用户单击链接按钮
  • Page调用OnInit以开始回发请求。链接按钮将被重新创建
  • 调用事件处理程序,动态创建文本框并将其添加到控件集合
  • 用户再次单击链接按钮
  • Page调用OnInit再次添加链接按钮。此时pnlFilter.Controls集合为空,但标记中静态声明的任何元素除外
  • 调用事件处理程序,并将新的文本框添加到控件列表中
  • 我不确定这是否是最佳实践,但我已经成功地使用了类似的模型(请注意,我还没有测试此代码-它可能需要调整):

    protected override void OnInit(事件参数e)
    {
    碱基.奥尼特(e);
    LinkButton lb=新的LinkButton();
    lb.ID=“lbAddFilter”;
    pnlFilter.Controls.Add(磅);
    lb.Text=“添加过滤器”;
    lb.Click+=新事件处理程序(lbAddFilter\u Click);
    //重新生成动态创建的控件
    foreach(PersistedControls中的var控制)
    {
    pnlFilter.Controls.Add(GenerateControl(control));
    }
    }
    私有IList_持久控制;
    private const string PersistedControlsSessionKey=“thispage\u persistedcontrols”;
    私有IList持久化控件
    {
    if(_persistedControls==null)
    {
    if(会话[PersistedControlsSessionKey]==null)
    会话[PersistedControlsSessionKey]=新列表();
    _persistedControls=会话[PersistedControlsSessionKey]作为IList;
    }
    返回持久化控件;
    }    
    void lbAddFilter\u单击(对象发送方,事件参数e)
    {
    TextBox tb=新的TextBox();
    tb.ID=“tb”+DateTime.Now.ToBinary().ToString();
    PersistedControls.Add(tb);
    pnlFilter.Controls.Add(tb);
    }
    

    请注意,我不确定是否要将实际控件对象添加到会话存储中-我认为控件ID存在问题,这将导致回发时出错(可能控件不可序列化?)。在我开发的解决方案中,我用GenerateControl方法生成了一个新的TextBox/Label/ComboBox/etc,并在PersistedControls集合中存储了一个自定义容器类,该类包含UI控件的各种属性,我需要在每个page Init上生成该控件。

    我将page_Init中的所有内容包装在!如果需要,我将返回。这样做会加载链接按钮和页面的初始状态,但当我单击其中一个链接按钮时,它们都会消失,页面上没有任何内容。每次回发时都需要重新创建它们,这是正确的。你需要在某个地方储存你已经拥有的数量。可能是Viewstate中的。如果在某个应用程序中创建了调查问卷(poll),并通过Web服务呈现,那么在这种情况下,您会怎么做?网站会获取一个调查问卷并为其呈现字段?在这种情况下,动态创建内容是唯一合适的选项否?是的,动态创建内容是有序的,但它不必像我尝试的那样是增量的;我假设您的web服务每次都返回所有结果,在这种情况下,您每次都呈现所有结果。通过使用viewstate和缓存,您的性能应该相当好。您是个天才。我试图实现与OP相同的功能,但这让我意识到,我可以不添加多个控件实例,而是在模式窗口中显示新控件,并在其模式中“保存”,提交到数据存储,然后非常轻松地将其加载到页面上。一千个谢谢。我已经花了三天和今晚的时间试图弄明白这个问题。动态的呢
    void lbAddFilter_Click(object sender, EventArgs e)
    {
        TextBox tb = new TextBox();
        tb.ID = "tb" + DateTime.Now.ToBinary().ToString();
        pnlFilter.Controls.Add(tb);
    }
    
    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);
    }