“未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配。”
这个错误的原理如下:
在页面回传,重新生成时,会自动装入回传前的视图状态。结合自己的实验,了解的这个过程大致如下:
Init事件 -> ViewState加载 -> Load事件 -> 其它页面事件(如回传前的按钮点击)-> PreRender事件
用户控件动态加载代码通常都位于Load事件中(比如我的BindData),或者位于atals的Triger空间EventHandler中,此时整个页面的ViewState
已经加载,就又通过一个有人称做Catch-up的机制再向PlaceHolder中新加载的控件追加其ViewState,而这个ViewState为回传前在相应位置的
控件的ViewState。所以如若新的控件与旧的类型控件不同的话,将出现前述错误。
这个错误解决起来也很简单:
在加载新的空间之前,先加载一下原来的控件,然后把PlaceHolder Clear掉,然后加载新的控件,至于如何保存原来的控件信息,当然也是使
用一个ViewState Property, 比如我的代码中的ControlType了!
protected string ControlType
...{
get
...{
if (ViewState["ControlType"] != null)
...{
return ViewState["ControlType"].ToString();
}
return "";
}
set
...{
ViewState["ControlType"] = value;
}
}
...........................
protected void Menu1_MenuItemClick(object sender, MenuEventArgs e)
...{
if (!e.Item.Value.Equals(ControlType))
...{
phContainer.Controls.Add(Page.LoadControl(ControlType)); //这个和前面在BindData里给ControlType赋值一起是为了
防止错误"Faild to load view state..."
phContainer.Controls.Clear();
ControlType = e.Item.Value;
phContainer.Controls.Add(Page.LoadControl(ControlType));
}
}