动态用户控件和viewstate - 我缺少什么

时间:2014-11-03 22:23:35

标签: asp.net user-controls dynamic-usercontrols

我想根据用户选择的DropDownList选择,在运行时动态地将usercontrols添加到我的页面中的PlaceHolder。像这样:

protected void Page_Init(object sender, EventArgs e)
{
    //get user's content selection
    int contentMode;

    if (!IsPostBack)
        contentMode = 1;
    else
        contentMode = Int32.Parse(Request.Form[ddlMode.UniqueID]);

    //load a user control
    ContentControl ucContent = null;

    switch (contentMode)
    {
        case 1:
            ucContent = LoadControl("~/Controls/SomeContent1.ascx") as ContentControl;
            break;
        case 2:
            ucContent = LoadControl("~/Controls/SomeContent2.ascx") as ContentControl;
            break;
    }

    ucContent.ID = "ucContent"; 

    phContentArea.Controls.Add(ucContent);
}

......这几乎可行,但经过两次回发后,我得到了这个:

无法加载viewstate。正在加载视图状态的控制树必须与在上一个请求期间用于保存视图状态的控制树匹配。例如,在动态添加控件时,在回发期间添加的控件必须与初始请求期间添加的控件的类型和位置相匹配。

...我读到的是由于第二次回发的控件不同于之前的回发。我试图通过给控件提供相同的ID和类型来防止这种情况,但是没有骰子。两个控件:

public partial class SomeContent1 : Foo.Bases.ContentControl
{
    //code
}

public partial class SomeContent2 : Foo.Bases.ContentControl
{
    //code
}

是否有一部分难题让我无法完成这项工作?我读过类似的问题,但建议并不富有成效。

感谢

2 个答案:

答案 0 :(得分:0)

在init事件中,您必须确保控制树与之前发布的控制树匹配;因此,如果删除控件,则需要在init运行后将其删除,即加载viewstate时。

此外,初始加载可能需要在PreInit中完成,您可以尝试查看是否也有帮助。

答案 1 :(得分:0)

一种不同的技术,但与我的问题不同,是在运行时添加所有内容控件,但将未选择的内容控件的可见性设置为False:

switch (contentMode)
{
    case 1:
        ucContent = LoadControl("~/Controls/SomeContent1.ascx") as ContentControl;
        phContentArea.Controls.Add(ucContent);

        ucContent = LoadControl("~/Controls/SomeContent2.ascx") as ContentControl;
        ucContent.Visible = false;
        ucContent.EnableViewState = false;
        phContentArea.Controls.Add(ucContent);    
        break;

    case 2:
        ucContent = LoadControl("~/Controls/SomeContent1.ascx") as ContentControl;
        ucContent.Visible = false;
        ucContent.EnableViewState = false;
        phContentArea.Controls.Add(ucContent);

        ucContent = LoadControl("~/Controls/SomeContent2.ascx") as ContentControl;
        phContentArea.Controls.Add(ucContent);
        break;
}

......但这并不像只加载所需的控件一样好。