在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
上一篇讨论了集合属性的使用,这一篇我们主要来讨论视图状态的自定义管理.
刚开篇的时后在最后把属性值用视图状态来保存时,得以把当前状态保存下来,关于视图状态的概述,这里不再累赘,没了解过的朋友可以在MSDN里输入 那么接下来将修改Custom的属性更改为视图状态保存,代码如下
#endregion
接下来我们更改Address的字属性,把其值保存在视图状态下. 代码如下:
#endregion
重新编译后,发现问题了,编译不通过,当前上下文不存在名称ViewState.如果这些属性直接定义在Custom控件下则一点问题也没有,但下面定义的是Address复杂属性的子属性.而Address属性又不能继承Control类,所以我们需要自定义一个ViewState属性 如下代码:
private bool _isTrackingViewState;
private StateBag _viewState; protected StateBag ViewState } 先定义两个变量,然后定义一个ViewState属性,ViewState类型本身便是一个StateBag类型.大家一定注意到了 IStateManager接口,下面还有一个TrackViewState方法.先不管他.重新编译下,编译通过,重新测试下,发现还是没有变化. MSDN上对ViewState能保存的值已经讲的很清楚了.你可以保存一些简单类型,但无法保存自定义类型,而我们定义的Address就是一个自定义类型.为保存自定义类型数据,所以我们需要自定义类型状态管理 自定义类型状态管理,那么我们就必须接触到IStateManager这个接口,此接口有一个属性和三个方法,如下 所以Address要继承IStateManager接口,并显示实现接口属性和方法,注意是显示实现 . 下面看Address类具体的自定义状态管理代码
#endregion
理解控件自定义的状态管理,你有必要了解控件的生命周期,了解控件生命周期,那问题就迎刃而解了. 大家可以翻阅MSND的控件执行生命周期 我个人认为最好的理解方法就是为上面代码设置三个断点, 如下图 好了,下面把我们测试的那个aspx页面设置为起始页,然后按F5,开始测试. 本该启动后跳到TrackViewState方法里,但没跳进来,好怪,而且自定义类型状态管理后页面并未保存其值. 让我们回到Custom类里,我们还需要为属性(复杂属性)定义状态管理. 本身Control也有一套默认的状态管理机制,而没有实现IStateManager接口 , 其实现如下: 对下面代码我认为是错误的,因为书上全是这么写的,我认为因先把_viewState显示转换为IStateManager类型, 因为StateBag本身是继承IStateManager接口,但MSDN中,我并没看到其实现IStateManager的方法,而是显示的实现,当我用反射机制查看其方法时,却又发现是有其方法的,但当你不把StateBag显示转换为IStateManager类型,而直接调用下面方法时,将会出错.如果书上是对的,还请看到此文的人指点一下,对此我已经疑惑很长时间了. 如果我是对的,那下面的_viewState因先显示转换为IStateManager类型,事实上我们都是这么做的.
}
下面再看如何在Custom类中自定义属性状态管理,当你定义了复杂类型时,你就需要重写上面的几个方法. 具体代码如下: 首先我们对属性进行视图状态的跟踪,然后重写了Control类的三个方法.其一方面调用了基类方法,一方面调用了Addres类的显示接口方法. Pair类为一个辅助类,用作存储两个相关对象的基本结构,下面根据调试结果来理解.在Custom类中对其三个方法设置断点.
#endregion
设置断点以后,启动起始页开始测试. 启动后第一步将会跳到Custom类的TrackViewState方法里面,执行完此方法后IsTrackingViewState将设置为true, 从而可以继续调用address的TrackViewState方法,另外可以看到address属性为空值,然后按F5,通过此方法继续 第二步将会跳到Custom类的SaveViewState方法里,发现baseState和thisState均为空,直接执行基类方法.按F5继续 第三步将会跳到Address类的TrackViewState方法里,_isTrackingViewState初始化时为false,执行此方法后将赋值为ture,然后调用_viewState的TrackViewState方法. 初始化的工作就完成了,然后我们点击确定按钮,重新执行. 重新跳到Custom类的TrackViewState方法里,步骤跟上面第一步一样,按F5,继续 跳到Address类的TrackViewState方法里,步骤跟上面第二步一样,按F5继续 跳到Custom类的SaveViewState方法里,此时address不再为null,此时会返回Pair构造函数. 然后会跳到Address类SaveViewState方法里,接着会跳回来,再执行Custom类的SaveViewState方法 以上调试方法不一定正确,但多调用会理解的更深刻. 我们还发现并未跳到LoadViewState方法里,以前的主要工作就是保存视图状态更改,接下来再次调试的话,就会跳到LoadViewState方法方法里面,这时你会发现savedState就是SaveViewState方法中保存下来的视图状态,可以看到其first和second值分别为Custom的页面属性和Address这个复杂属性的值. 视图状态以键/值的方式保存,有一个属性为Dirty,表示StateItem是否被修改过,可以通过SetDirty方法和SetItemDirty方法给StateItem添加Dirty标记.
internal void SetDirty()
} 如果此StateItem标记为Dirty的话,则在SaveViewState方法中以键/值的方式保存到ArrayList中. SaveViewState方法和LoadViewState方法执行的是相反的操作.我们在页面上看到的值,总是LoadViewState方法反序列化视图状态.大家可以具体去了解StateBag类默认情况下SaveViewState方法和LoadViewState方法的实现过程. 当控件禁用视图状态时将不再执行SaveViewState和LoadViewState,可以去调试一下就知道了. 还需要注意的是,我们了解视图状态可以保存的类型,其也是同过类型转换器来转换此类型,否则的话将以二进制串行化功能来串行化数值得,这样降低了效率,所以我们还需要为其定义一个类型转换器,第九篇的时候已经讲过怎么定义了,这里就不列代码了,只是需要注意就是. 此外asp.net2.0中加入了控件状态,因为视图状态要么全开,要么全禁用,控件状态则是为弥补这一点,大家可以看MSDN,也可参考相关文章. asp.net2.0中还可以对视图状态进行分块处理,你需要在web.config里如下设置
<system.web>
<pages maxPageStateFieldLength="1000" > <system.web> asp.net2.0还加入了视图状态持久性机制,大家可以在博客园参考相关文章,这里就当了解下有这种机制存在. 好了,就写到这里,个人认为视图状态是很重要的,下面很多东西都要涉及到它,所以要好好理解这个东西. 写的比较乱,对视图状态我真的比较敏感,很难理解,也难表达,可能很多地方写错,还请指出,这样才能提高 示例代码下载 |
请发表评论