如何将 TabContainer 保存到 Viewstate?

How to save TabContainer to Viewstate?

我一直在努力将 TabContainer 保存到将加载该 TabContainer 的所有 TabPanel 的视图状态变量。 (页面加载速度会更快吗?)。 如果问题格式不正确,请原谅我;我还是 asp.net 的新手,这是我的代码:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        CreateTabbedPanel();
        Response.Write("New Tabs Loaded");
    }
    else
    {
        // Here i would need to load the TabContainer from the viewstate variable
        Response.Write("Tabs Loaded from ViewState");
    }
}

private void CreateTabbedPanel()
{
    TabPanel tp = null;

    string CS = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
    using (SqlConnection con = new SqlConnection(CS))
    {
        SqlCommand cmd = new SqlCommand("select Description from TblProductType", con);
        con.Open();
        SqlDataReader rdr = cmd.ExecuteReader();
        while (rdr.Read())
        {
            tp = new TabPanel();
            tp.HeaderText = rdr["Description"].ToString();                    
            TabContainer1.Tabs.Add(tp);
        }
    }
    // Here i would need to create the viewstate variable
}

这是我的网络表单:

<form id="form1" runat="server">
    <div>
        <ajaxToolkit:TabContainer ID="TabContainer2" runat="server" 
           ActiveTabIndex="1" AutoPostBack="false">
        </ajaxToolkit:TabContainer>
    </div>
</form>

我需要做什么?

如果您希望将 .Net 对象保存到 ViewState,您需要确保该对象支持 serialization/deserialization。但是,这不太可能提高性能。

ViewState 数据呈现到特定的隐藏字段中。如果将复杂对象保存到 ViewState 中,则会大大增加 HTML 页面大小。接下来,serialization/deserialization也需要时间。

最后,由于 ASP/NET page and control life cycle,您无法在 ViewState 中存储 ASP.NET 控件。当您创建控件并将其添加到页面控件层次结构中时,它会经历 ASP.NET 生命周期的所有阶段:初始化、加载、呈现、[保存在 ViewSate 中]、卸载。下次从 ViewState 中获取控件时,控件状态将为 'after-render'。如果将此类控件添加到新的页面控件层次结构中,处于'after-render'状态的控件将再次开始Init、Load和Render阶段。虽然它可以在以下情况下运行原始控件(Labes、TextBoxes等),它完全打破了控件的生命周期,并在复杂控件中导致各种奇怪的问题。

如果您动态创建 ASP.NET 控件,我强烈建议您 re-create 在每个新页面请求中使用它们,因为 ASP.NET 页面生命周期需要.

假设您只需要保存几个标签名称,您可以使用ViewState。否则我会推荐 Session 因为它允许在服务器端存储复杂的 objects 而不必 post 它们进入页面,它需要更少的代码但你还需要处理 session 已过期。

tabs的collection是read-only,不可序列化等。但是这段代码可以用来保存headers到CreateTabbedPanel()

private void SaveTabs()
{
    TabPanel[] tabs = new TabPanel[TabContainer1.Tabs.Count];
    TabContainer1.Tabs.CopyTo(tabs, 0);
    ViewState["tabs"] = tabs.Select(t=>t.HeaderText).ToArray();
}

当页面加载未 post 返回时:

private void LoadTabs()
{
    string[] headers = (string[])ViewState["tabs"];
    if(headers!=null)
    {
        foreach (string header in headers)
        {
            TabContainer1.Tabs.Add(new TabPanel() { HeaderText = header });
        }
    }
}