2010-11-18 72 views
15

我知道这个问题已经被问过几千次了,之前我一直在努力,但由于某种原因,我无法完成我想完成的任务......我有一个动态添加的LinkBut​​ton,点击后会动态添加一个控件(在本例中为一个文本框)到同一个面板。其目的是不断添加与LinkBut​​ton点击次数相同的控件(即,我点击一次,一个框,然后再次点击会给我2个框,另一个点击会添加一个第三个)。在下面的代码中,我使用序列化的当前日期和时间为每个文本框控件创建一个唯一的ID。ASP.NET动态创建控件和Postback

当我执行代码时,单击“添加过滤器”将会生成一个新的文本框,但是一旦再次单击将创建一个新的文本框,并在其之前处理该文本框。相反,我想坚持以前的文本框以及其中提交的任何数据。

您的帮助表示赞赏。

在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); 
} 

回答

16

对于其他人试图做这样的事情:不要。相反,想一想信息流,并了解有更好的方法去做。输入控件不需要动态创建。它们可以是静态的,并且在填写并提交时,该信息必须位于某处(例如数据库,缓存,会话)。一旦它在那里,回发,循环通过您的存储选择的所有项目,并为他们创建一个显示。

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

+0

在某个应用程序中创建问卷(民意调查)并通过网络服务 呈现的情况下,您会做什么?网站会提取投票并为其显示字段? 在这种情况下动态创建内容是唯一合适的选项不是? – Sander 2011-05-31 09:14:26

+0

是的,动态创建内容是按顺序的,但它不必像我试图做的那样是渐进的;我假设您的网络服务每次都会返回所有结果,在这种情况下,您每次都会呈现所有结果。通过使用视图状态和缓存,你的表现应该很好。 – 2011-05-31 16:23:01

+1

你是个天才。我试图实现与OP相同的功能,但是这让我意识到我可以不添加多个控件实例,只需在模式窗口中显示新控件,并在她的模式中“保存”,提交到数据存储区并然后很容易地加载到页面上。一千谢谢你。我已经花了3天时间,今天晚上都试图弄清楚这一点。 – 2014-07-23 14:30:36

0

尝试增加,

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

我在!IsPostBack中包裹了Page_Init中的所有内容if。这样做会加载链接按钮和页面的初始状态,但是当我点击其中一个链接按钮时,它们全部消失并且页面上没有任何内容。 – 2010-11-18 15:36:27

1

我相信,你将需要在重新每个控制每回发。

我知道Repeater控件在数据绑定时存储足够的关于它的子项的信息以重新创建它们......您可能可以使用它来节省一些工作。

+0

您需要在每次回传中重新创建它们是正确的。某处你需要储存你已有的数量。也许在Viewstate或其他东西。 – Remy 2010-11-18 19:21:04

11
void lbAddFilter_Click(object sender, EventArgs e) 
{ 
    TextBox tb = new TextBox(); 
    tb.ID = "tb" + DateTime.Now.ToBinary().ToString(); 
    pnlFilter.Controls.Add(tb); 
} 

这不会起作用 - 这是一个生命周期问题,正如您在问题中推断的那样。有很多方法可以解决这个问题,但瓦纳的建议是最灵活的。

这里发生的事情是,您在事件处理程序中调用Controls.Add并将控件添加到控件列表中,并且在下一个请求中(无论是部分回发,完整回发还是新页面命中),那个控制已经消失了,因为你没有坚持到任何地方。

这里发生的事情在你的页面事件生命周期现在:

  1. 页面调用的OnInit,并增加你的LinkBut​​ton的
  2. 用户点击LinkBut​​ton的
  3. 页面调用的OnInit开始回发请求。LinkBut​​ton的是重新
  4. 事件处理程序被调用,动态创建文本框的,并把它添加到控件集合
  5. 用户点击LinkBut​​ton的再次
  6. 页面调用的OnInit再次添加LinkBut​​ton的。此时pnlFilter.Controls集合是空的,除了您在标记中静态声明的任何元素。
  7. 调用事件处理函数,并将新的TextBox添加到控件列表中。

我不知道,这是最好的做法,但我已经与此类似(注意,我没有测试此代码 - 这可能需要调整)一个模式的成功:

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); 
} 

请注意,我不确定是否将实际的控件对象添加到会话存储 - 我相信存在控件ID会在回发时导致错误(也许控件不可序列化?)的问题。在我开发的解决方案中,我生成了一个新的TextBox/Label/ComboBox /等同于GenerateControl方法,并在PersistedControls集合中存储了一个自定义容器类,该集合包含需要生成的UI控件的各种属性它在每个页面上初始化。