1

过去,在开发动态加载多控件单页类型的应用程序时,我对视图状态非常头疼。原因是控件必须在OnInit阶段添加,而不是之后。由于我正在处理一个控制事件(例如,下拉列表中的 selectedIndexChanged),我将它们加载到事件处理程序阶段。我知道子控件页面循环追赶,但我注意到有时它不起作用。

我又一次接到了开发这样一个应用程序的任务。这次我决定采取不同的方法。对于那些根据其值加载动态控件的选择控件,我将在 OnInit 阶段检查它们的回发响应值(来自 Request.Form)并立即加载控件。我不会从事件处理程序阶段加载任何动态控件,因为这正好在 OnPreRender 之前并且为时已晚。

总而言之:
在页面周期的早期(例如 OnInit)从 Request.Form 集合中检查控件的值然后执行操作,而不是在页面周期的后期从实际控件中检查该值有什么缺陷?

4

1 回答 1

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 上编写的。它没有被编译或调试。但你明白了。

于 2013-10-11T14:07:55.043 回答