过去开发动态加载多控制单页类型应用程序时,我遇到了很多关于viewstate的问题。原因是必须在 OnInit 阶段添加控件,而不是之后。由于我正在处理一个控件事件(例如,dropdownlist上的selectedIndexChanged),我在事件处理程序阶段加载它们。我知道儿童控制页面循环追赶,但我注意到有时它只是不起作用。
我再一次负责开发这样的应用程序。这次我决定采取不同的方法。对于那些根据其值加载动态控件的选择控件,我将在OnInit阶段检查它们的回发响应值(来自Request.Form)并立即加载控件。我不会从事件处理程序阶段加载任何动态控件,因为这是在OnPreRender之前,而且为时已晚。
总结:
在页面周期的早期(例如OnInit)从Request.Form集合中检查控件的值然后执行操作,而不是在页面循环的后期检查实际控件的值会有什么陷阱?
答案 0 :(得分:0)
其中一个陷阱是,如果<form>
中没有包含控件,则它将不存在。我建议继续在事件处理程序阶段添加它们 - 因为那时你知道要添加什么 - 但是存储必要的信息以重构ViewState
或SessionState
中的那些控件。
通过这样做,您将能够在OnInit
中重新创建它们,但不必处理您现在所处的道路周围的其他一些复杂问题。
所以,假设您发现需要构建控件。你要建造它:
var tb = new TextBox();
tb.ID = "myTextBox";
...
但您还要保存必要的状态信息:
this.ViewState.StoreControl(typeof(TextBox), "myTextBox");
然后只构建扩展方法:
public static void StoreControl(this StateBag vs, Type controlType, string name)
{
var dynamicControls = vs["DynamicControls"] as List<Tuple<Type, string>>;
if (dynamicControls == null)
{
dynamicControls = new List<Tuple<Type, string>>();
vs["DynamicControls"] = dynamicControls;
}
var t = dynamicControls.FirstOrDefault(tp => tp.Item2 == name);
if (t == null) { dynamicControls.Add(Tuple.Create(controlType, name)); }
}
然后在OnInit
你可能会做这样的事情:
var dynamicControls = vs["DynamicControls"] as List<Tuple<Type, string>>;
if (dynamicControls != null)
{
foreach (var tp in dynamicControls)
{
Control c = Activator.CreateInstance(tp.Item1) as Control;
c.ID = tp.Item2;
this.Controls.Add(c);
}
}
注意:此代码是在SO上编写的。它没有被编译或调试。但是你明白了。