Spiga

深入理解 ViewState

2006-10-29 17:40 by Cat Chen, 6355 visits, 收藏, 编辑

上个星期写了一篇《控件 ViewState 属性的值保存去哪里了》,解释了Control.ViewState最终还是通过Control.SaveViewState和Control.LoadViewState这两个方法存取的。文章中有一句话可能会让大家感到疑惑的:“我们在OnInit之后使用this.ViewState[key]读写时该属性都为true”,其中“该属性”指StateItem.IsDirty。到底为什么IsDirty属性在OnInit之后总是为true呢?参考了TRULY Understanding ViewState,我终于明白到其实它并非总是为true,详细原因请听我慢慢说。

首先要让大家来看的是StateBag.TrackViewState方法,这个方法在控件OnInit时就会被调用,而它的作用就是让StateBag开始跟踪StateItem的变化,任何变化都将导致该StateItem的IsDirty属性变为true。也就是说,在OnInit之前,IsDirty属性是false的,并且无论你如何设置Value属性的值都不会改变IsDirty属性。在OnInit之后,IsDirty属性也保持着false,直到你第一次改变Value属性的值(指通过this.ViewState[key]的方法改变)。到了SaveViewState的阶段,只有IsDirty属性为true的StateItem才会被保存下来。

为什么要如此设计呢?例如一个通过声明性定义的Label的Text属性,在ASPX中它被赋了初值,然后该初值自然通过ViewState["Text"]来持久。在下一个页面生命周期,首先OnInit时这个Label的Text属性会加载ASPX中声明性定义的初值,然后LoadViewState时会用ViewState中读取到的ViewState["Text"]来覆盖它。然而除非你在上一个页面生命周期以编程的方式改变了Text属性,否则ViewState["Text"]还是初值,那么你就是用ViewState["Text"]保存初值去覆盖声明性定义的初值,同一个值这样覆盖完全没意义,而且还浪费了ViewState的空间。为了解决这个资源浪费的问题,凡是声明性定义之后没改变到的值就不应该使用ViewState来持久,而详细的实现就是上面说的TrackViewState机制了。

说到这里,Control.ViewState已经解释完毕,如果你是控件设计者你可以放心地按以下方式把控件属性存放到ViewState中:
public string Text
{
  get {return this.ViewState["Text"] as string;}
  set {this.ViewState["Text"] = value;}
}
它的内部机制会懂得区分你存进去的值是不是ASPX上声明性定义的初值,然后决定是否持久该值。同时,如果你在任何阶段想改变一个ViewState值是否持久的决定,可以通过ViewState.SetItemDirty(key, dirty)来改变,这基本上已经满足了所有控件开发人员的需求。

Add your comment

7 条回复

  1. #1楼 Dflying Chen      2006-10-29 18:23
    你的很多文章都非常好的,为什么不发到首页呢?
     回复 引用 查看   
  2. #2楼 Dflying Chen      2006-10-29 18:27
    我觉得你的大部分文章都超过了首页的文章质量!应该发布到首页,让大家分享!
     回复 引用 查看   
  3. #3楼 Jeffrey Zhao      2006-10-29 21:39
    呵呵,没错
     回复 引用 查看   
  4. #4楼 Dflying Chen      2006-10-29 21:57
    前面几篇文章也应该发到首页的
     回复 引用 查看   
  5. #5楼[楼主] cathsfz      2006-10-30 00:28
    @Dflying Chen
    @Jeffrey Zhao
    我把前面的一些精选发上首页了,但是由于发表日期的问题,无法排上首页,呵呵……
     回复 引用 查看   
  6. #6楼 Jacky Lee[未注册用户]2007-05-06 21:17
    正是,陈兄的文章都写得很专业
     回复 引用   
  7. #7楼 Kai.Ma      2008-03-29 17:36
    Now,I am "TRULY Understanding ViewState".:)Thanks.
     回复 引用 查看