ASP.NET动态控件计数(随时创建控件)

我正在尝试创建一个复合ASP.NET控件,让您构建一个可编辑的控件集合。

我的问题是,当我按下添加或回发按钮(除了回发表单之外什么都没做)时,在文本框中输入的任何值都将丢失。

当回发之间的控件数量发生变化时,我无法使其工作。 我需要基本上能够在控制生命周期中的两个不同时间重新创建控制树,具体取决于视图状态属性ControlCount

此测试可用于重现该问题:

 public class AddManyControl : CompositeControl { protected override void OnLoad(EventArgs e) { base.OnLoad(e); EnsureChildControls(); } protected override void CreateChildControls() { var count = ViewState["ControlCount"] as int? ?? 0; for (int i = 0; i < count; i++) { var div = new HtmlGenericControl("div"); var textBox = new TextBox(); textBox.ID = "tb" + i; div.Controls.Add(textBox); Controls.Add(div); } ViewState["ControlCount"] = count; var btnAdd = new Button(); btnAdd.ID = "Add"; btnAdd.Text = "Add text box"; btnAdd.Click += new EventHandler(btnAdd_Click); Controls.Add(btnAdd); var btnPostBack = new Button(); btnPostBack.ID = "PostBack"; btnPostBack.Text = "Do PostBack"; Controls.Add(btnPostBack); } void btnAdd_Click(object sender, EventArgs e) { ViewState["ControlCount"] = (int)ViewState["ControlCount"] + 1; } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); // If I remove this RecreateChildControls call // the collection lags behind each postback // because the count is incremented in the btnAdd_Click event handler // however, the values are not lost between postbacks RecreateChildControls(); } } 

如果你想使用ASP.NET的自定义控件,你必须遵循它的规则和挑剔! 当您开始在自定义控件中使用OnPreRender时,您知道90%的时间都在错误的轨道上。

通常,使用ViewState的最佳方式是声明由它备份的属性,就像标准的ASP.NET控件一样(.NET Reflector已经成为我的老师多年了!)。 这样,它将在事件的生命周期中自然地被读取和保存。

这是一个代码似乎做你想要的,非常自然,没有任何技巧:

 public class AddManyControl : CompositeControl { private void AddControl(int index) { var div = new HtmlGenericControl("div"); var textBox = new TextBox(); textBox.ID = "tb" + index; div.Controls.Add(textBox); Controls.AddAt(index, div); } protected override void CreateChildControls() { for (int i = 0; i < ControlsCount; i++) { AddControl(i); } var btnAdd = new Button(); btnAdd.ID = "Add"; btnAdd.Text = "Add text box"; btnAdd.Click += new EventHandler(btnAdd_Click); Controls.Add(btnAdd); var btnPostBack = new Button(); btnPostBack.ID = "PostBack"; btnPostBack.Text = "Do PostBack"; Controls.Add(btnPostBack); } private int ControlsCount { get { object o = ViewState["ControlCount"]; if (o != null) return (int)o; return 0; } set { ViewState["ControlCount"] = value; } } void btnAdd_Click(object sender, EventArgs e) { int count = ControlsCount; AddControl(count); ControlsCount = count + 1; } } 

我相信你必须将控件添加到视图状态。