viewstate

internal object SaveViewState()
{
    ArrayList list 
= null;
    
if (this.bag.Count != 0)
    {
        IDictionaryEnumerator enumerator 
= this.bag.GetEnumerator();
        
while (enumerator.MoveNext())
        {
            StateItem item 
= (StateItem) enumerator.Value;
            
if (item.IsDirty)
            {
                
if (list == null)
                {
                    list 
= new ArrayList();
                }
                list.Add(
new IndexedString((string) enumerator.Key));
                list.Add(item.Value);
            }
        }
    }
    
return list;
}

 从上面代码看只有 IsDirty=true(发生改变的数据)才会被序列化保存在隐藏字段中
bag   ==>  dictionary(string,StateItem)
 
那IsDirty什么时候才会是true呢.初始的时候默认值可是false
 
public StateItem Add(string key, object value)
{
    
if (string.IsNullOrEmpty(key))
    {
        
throw ExceptionUtil.ParameterNullOrEmpty("key");
    }
    StateItem item 
= this.bag[key] as StateItem;
    
if (item == null)
    {
        
if ((value != null|| this.marked)
        {
            item 
= new StateItem(value);
            
this.bag.Add(key, item);
        }
    }
    
else if ((value == null&& !this.marked)
    {
        
this.bag.Remove(key);
    }
    
else
    {
        item.Value 
= value;
    }
    
if ((item != null&& this.marked)
    {
        item.IsDirty 
= true;
    }
    
return item;
}


public object this[string key]
{
    
get
    {
        
if (string.IsNullOrEmpty(key))
        {
            
throw ExceptionUtil.ParameterNullOrEmpty("key");
        }
        StateItem item 
= this.bag[key] as StateItem;
        
if (item != null)
        {
            
return item.Value;
        }
        
return null;
    }
    
set
    {
        
this.Add(key, value);
    }
}
 

 
 我们看上面的代码只有 赋值的时候也就是 ViewState["Text"] = ....
调用Add方法,
 if ((item != null) && this.marked)
要满足上面2个条件就会被标记改变.
 所赋值在字典中没有存放过,那么会new一个StateItem 并且加入到bag中.
如果存在了直接赋值,所有只要执行ViewState属性赋值操作,那么第一个条件肯定会满足了.
那么第二个条件在这



internal void TrackViewState()
{
    this.marked = true;
}




 
只要我们执行了 TrackViewState 那么marked就会被标记为true了.
所以要想记录状态,必须调用控件的TrackViewState 方法,
可能你会认为根据赋值前后ViewState是否存在变化然后再标记是否是脏数据这样更加符合常理。但是必须注意的是ViewState的项是可以存储任何类型的值的(实际上任何赋值给ViewState的变量都会被装箱为Object类型的变量),所以比较赋值前后的值是否一致实际上并没有变面上看的那么容易。而且不是每种类型都是先了IComparable的接口,所以通过调用CompareTo方法来进行比较也是不可行的。另外还有一个原因,我们知道ViewState还需要将其内部的数据进行序列和反序列化,当这些操作发生后,你得到的对象已经不是原来那个对象了,所以比较对象之间的引用也是无法完成的。基于以上这些原因,ViewState采取了一种简单的做法,也就意味着ViewState的数据变化跟踪也是一个简要的跟踪。

 

 

下面我们再看一下,ViewState是如何恢复值的

internal void LoadViewState(object state)
{
    
if (state != null)
    {
        ArrayList list 
= (ArrayList) state;
        
for (int i = 0; i < list.Count; i += 2)
        {
            
string key = ((IndexedString) list[i]).Value;
            
object obj2 = list[i + 1];
            
this.Add(key, obj2);
        }
    }
}
保存的时候是连续Add到列表中,

list.Add(new IndexedString((string) enumerator.Key));
list.Add(item.Value);
所以恢复到ViewState的时候必须间隔一下取值.

 

应用:

1 this.PerformPreInit();

    this.OnPreInit(EventArgs.Empty);
    this.InitializeThemes();
    this.ApplyMasterPage();
    this._preInitWorkComplete = true;

2 this.InitRecursive(null);

    control.GenerateAutomaticID(); 

    control._page = this.Page;
    control
.InitRecursive(namingContainer);

    this.OnInit(EventArgs.Empty);
   
this.TrackViewState();

if (this.IsPostBack)
    this.LoadAllState();------>base.LoadViewStateRecursive(second.Second);
    this.ProcessPostData(this._requestValueCollection, true);------->

 

4LoadRecursive()
     this.OnLoad(EventArgs.Empty);
     this._occasionalFields.Controls[i].LoadRecursive();

 

5if (this.IsPostBack)
    this.ProcessPostData(this._leftoverPostData, false);
    this.RaiseChangedEvents();
    this.RaisePostBackEvent(this._requestValueCollection);

6this.PreRenderRecursiveInternal();
    this.OnPreRender(EventArgs.Empty);
    this._occasionalFields.Controls[i].PreRenderRecursiveInternal();






 
 
 
posted on 2011-04-06 02:36  kasafuma  阅读(343)  评论(0编辑  收藏  举报