我的观点是:ViewState有可能成为你最好的朋友,也有可能成为你最坏的敌人—这要依赖于你使用它的方式来决定。如果你在以前曾经使用过ViewState,那么,你肯定会喜欢新的ControlState。
关于ViewState的最令人头痛的问题之一就是,它的“all-or-nothing”状态管理方法。页面开发者可以很容易地决定在任何控 件级,页面级或在整个站点级(经由web.config)上关闭ViewState。事实上,如果你在整个站点级上通过web.config关闭 ViewState的话,那么,你不妨猜测一下你还能够在其它什么地方关闭它?答案是:还可以在machine.config中实现—在此情况下,它能够 影响到同一服务器上的所有站点。如果一个页面开发者决定关掉在ViewState中实现状态管理的能力,那么,你的控件生成有可能出现部分不可用,或更有 甚者—完全不可用。
为此,在新版本中,微软创建了ControlState—旨在解决这一问题。页面开发者不能关掉ControlState,因此使用它进行属性选择更为安全。
使用ControlState与使用ViewState几乎完全一致。然而,ControlState并没有提供象ViewState这样的一 个变量,而是提供了称为SaveControlState和LoadControlState的方法以便于你的控件能够进行重载。这些方法与 SaveViewState和LoadViewState方法的工作原理完全一致。
因为ControlState在属性语句中没有提供一个相应的变量,所以,你必须借助于ASP.NET开发者以前在他们的对象中所使用的成员变量(属性语句)来实现相同的功能。
以下是引用片段: Protected _MailServer As String = "First name:" Public Property MailServer() As String Get Return _ MailServer End Get Set(ByVal value As String) _MailServer = value End Set End Property |
然而,因为我使用了一个标准的成员变量来保存值,所以我需要一种方法以便把数据存储在ControlState中—这正是前面提到的方法“登 场”的原因。就象在它们相应的ViewState方法中那样,ASP.NET将在页面生命周期内调用这两个方法。其中,SaveViewState方法返 回一个将被持久存储的对象类型。通过返回一个对象数组,这个方法可以存储多个值。并且,就象发生在SaveViewState方法中一样,也是使用数组的 0下标元素来调用基类的SaveControlState方法。
以下是引用片段: Protected Overrides Function SaveControlState() As Object Dim state() As Object = New Object(2) {} state(0) = MyBase.SaveControlState() state(1) = _MailServer Return state End Function |
注意:LoadControlState方法以一个对象作为参数—这个对象是以前在SaveControlState中返回的一个对象。在这个 方法中,我重新分配了成员变量—通过把该参数转换为一个对象数组,然后获得每个下标的值。与以前一样,我使用数组的0下标来调用基类的 LoadControlState方法。
以下是引用片段: Protected Overrides Sub LoadControlState( _ ByVal savedState As Object) If savedState IsNot Nothing Then Dim state() As Object = CType(savedState, Object()) MyBase.LoadControlState(state(0)) _MailServer = CType(state(1), String) End If End Sub |
借助于这些方法来存储数据,在页面开发者关掉ViewState时,控件就不会出现前面那些麻烦。
你可能对ControlState的存储位置感到惊讶;它对应于另一个生成到HTML页面中的隐藏的文本框。就象在ViewState情况下数 据被存储在__ViewState隐藏文本框中类似,ASP.NET 2.0使用__ControlState隐藏文本框来存储ControlState数据。
遗憾的是,微软没有向开发者提供内在地使用ControlState的能力—就象在ViewState情况下那样。所以,为了 ControlState使用,你需要注册你的控件。你可以重载控件的OnInit事件并且调用Page对象的 RegisterRequiresControlState方法。
以下是引用片段: Protected Overrides Sub OnInit(ByVal e As System.EventArgs) MyBase.OnInit(e) If Page IsNot Nothing Then Page.RegisterRequiresControlState(Me) End If End Sub |
现在,你可以使用ControlState来存储你认为足够重要的数据—如果不把它存储起来,那么你的控件可能生成一些无用的内容。
记住,你在设计时刻对属性的修改将被硬编码到该控件的ASPX声明中,从而在相邻的再次回寄之间自动地存储。然而,如果表单上的一个行为改变了 一个控件的属性,那么,这将会激活状态管理机制的使用。如果不把该属性存储在一个状态中,那么,在下一次回寄时它将恢复到“硬编码”状态。
现在,总的来看,我们应该把与外观相关的属性存储在ViewState中,而把与行为相关的属性存储在ControlState中。通过这种方式,如果一个页面开发者关掉ViewState,那么你的控件尽管可能看起来样子别扭,但是仍能正确工作。
本文转自朱先忠老师51CTO博客,原文链接:http://blog.51cto.com/zhuxianzhong/59763
,如需转载请自行联系原作者