您的位置:首页 > 移动开发 > Objective-C

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

2008-06-11 19:14 519 查看
前段时间看了一篇金旭亮老师的文章(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。

 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐