我想在运行时将用户控件动态添加到页面中的PlaceHolder中,基于用户选择的DropDownList选择。类似这样的东西:
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);
}
这几乎有效,但在两次回邮后,我得到了这个:
无法加载视图状态。视图状态加载到的控制树必须与上次请求期间用于保存视图状态的控制树匹配。例如,当动态添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控制器的类型和位置相匹配
我读到的原因是第二次回发时的控件与前一次回发不同。我试图通过给控件相同的ID和类型来防止这种情况,但没有骰子。两个控件:
public partial class SomeContent1 : Foo.Bases.ContentControl
{
//code
}
public partial class SomeContent2 : Foo.Bases.ContentControl
{
//code
}
有没有我遗漏的一部分来完成这项工作?我读过类似的问题,但这些建议并不富有成效。
感谢
在init事件中,您必须确保控制树与上一个发布的控制树匹配;因此,如果删除控件,则需要在init运行后(即加载viewstate时)将其删除。
此外,初始加载可能需要在PreInit中完成,您可以尝试看看这是否也有帮助。
一种不同的技术是在运行时添加所有内容控件,但将未选中控件的可见性设置为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;
}
但这感觉不如只加载所需的控件好。