我的控件开发经历(4)——viewstate如何保存到页面

前段时间看了一篇金旭亮老师的文章(http://blog.csdn.net/bitfan/archive/2008/06/02/2504743.aspx),收获颇丰,但也有一个疑问:

viewstate保存到页面时与代码顺序有关。可以在页面上丢一个服务端button,试验以下代码:

protected void Page_Load(object sender, EventArgs e)

    {

        Panel p = new Panel();

 

        // form1.Controls.Add(p);//(1)

       

        if (!IsPostBack)

        {

            p.Style.Add("width", "100px");

            p.Style.Add("height", "100px");

            p.Style.Add("border", "solid 1px red");

        }

 

        form1.Controls.Add(p);//(2)

    }

 

点击button后,add放在(1)处可使 p 不变,放在(2)处 p 不见了。原因是放在(1)处 p 的style被加到页面的viewstate隐藏域,在提交后loadviewstate生命周期还原给p。

而放在(2)处没有被加到隐藏域。(可以用看viewstate的工具察看)。

那为什么与代码顺序有关呢?这两天用reflector总算看出点道道,写下来免得忘了。

(1)style其实就是:CssStyleCollection

public sealed class CssStyleCollection

{     ...     private StateBag _state; // 关键b     ...

    public void Add(string key, string value); // 关键a    ...

}

(2)关键a代码:

public void Add(string key, string value)

{    

   if (string.IsNullOrEmpty(key))    

   {        

        throw new ArgumentNullException("key");    

   }   

  if (this._table == null)    

{       

      this.ParseString();   

  }    

this._table[key] = value;    

     if (this._intTable != null)   

  {        

           HtmlTextWriterStyle styleKey = CssTextWriter.GetStyleKey(key);       

               if (styleKey != ~HtmlTextWriterStyle.BackgroundColor)        

              {            

                    this._intTable.Remove(styleKey);       

             }    

    }    

     if (this._state != null)    

   {          this._state["style"] = this.BuildString(); // 关键c    

    }         this._style = null; }

关键c告诉我们对style调用add就会往this._state["style"]里增加,原因是:

(3)statebag代码:

public sealed class StateBag : IStateManager, IDictionary, ICollection, IEnumerable {     ...

    public StateItem Add(string key, object value); // 关键e     ...

    public object this[string key] { get; set; } // 关键d     ...

}

关键d代码:

 

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); // 关键e    

       } }   关键e代码:

 

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); // 关键f             

              this.bag.Add(key, item);          }      }     

     else if ((value == null) && !this.marked)      {         

                this.bag.Remove(key);      }      else      {        

                 item.Value = value;      }      

   if ((item != null) && this.marked) //关键g      {         

               item.IsDirty = true;     

    }     

 

           return item;  }

(4)在关键f处 new 一个stateitem时默认isdirty是false,证据:

 

 

internal StateItem(object initialValue) {    

        this.value = initialValue;    

      this.isDirty = false; }

关键g处:this.marked 在没有调用过trackviewstate时是一定是false,证据:statebag的构造函数:

 

public StateBag(bool ignoreCase) {     

     this.marked = false;    

    this.ignoreCase = ignoreCase;    

     this.bag = this.CreateBag();

}

所以如果在style.add之前没有使关键b处style实例的_state的marked变成true, 那么加进_state的stateitem的isdirty一定是false,干净的东西就不会加到页面隐藏域了。 而controls.add会默认调用trackviewstate,使在它调用之后style.add增加的东西变脏。 这就是全部的原因。但这里遗留一个问题:_state是如何在saveviewstate中被操作的。

有时间我会继续reflector。

   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值