我正在尝试创建一个复合 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;
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)