C# ASP.NET动态控件计数(边创建控件边运行)
我正在尝试创建一个复合ASP.NET控件,让您可以构建一个可编辑控件集合 我的问题是,当我按下add或postback按钮(除了回发表单外,它什么也不做)时,文本框中输入的任何值都会丢失 当回发之间的控件数量发生变化时,我无法让它工作。根据视图状态属性C# ASP.NET动态控件计数(边创建控件边运行),c#,asp.net,webforms,C#,Asp.net,Webforms,我正在尝试创建一个复合ASP.NET控件,让您可以构建一个可编辑控件集合 我的问题是,当我按下add或postback按钮(除了回发表单外,它什么也不做)时,文本框中输入的任何值都会丢失 当回发之间的控件数量发生变化时,我无法让它工作。根据视图状态属性ControlCount,我基本上需要能够在控件生命周期的两个不同时间重新创建控件树 此测试可用于重现问题: public class AddManyControl : CompositeControl { protected overri
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();
}
}
公共类AddManyControl:CompositeControl
{
受保护的覆盖无效加载(事件参数e)
{
基础荷载(e);
ensureChildControl();
}
受保护的覆盖无效CreateChildControls()
{
变量计数=视图状态[“控制计数”]为int???0;
for(int i=0;i
我认为必须将控件添加到视图状态 如果你想玩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;
}
}
公共类AddManyControl:CompositeControl
{
私有void AddControl(int索引)
{
var div=新的HtmlGenericControl(“div”);
var textBox=新的textBox();
textBox.ID=“tb”+索引;
div.Controls.Add(文本框);
控件。AddAt(索引,div);
}
受保护的覆盖无效CreateChildControls()
{
for(int i=0;i
不,它不是那样工作的。这是另外一回事。某些生命周期事件不会第二次运行(因为正在重新创建控制树)。由于每次回发时都会从头开始重新添加所有文本框,因此它们如何恢复其文本值?asp.net做了什么吗?这是非常微妙的,这是肯定的。但您的意思是,我所要做的就是避免在预渲染期间重新创建控件集合,如果我在事件完成处理后再创建控件集合,那就没问题了?我现在通过远离on PreRender事件使它工作了,我也不能期望能够重新创建控件并保持视图状态。真是太遗憾了。我必须在该事件期间仅添加新控件才能使其工作。我只是想重新创建控件集合,并希望它能工作。但它不。。。