我的控件开发经历(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。
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。
相关文章推荐
- Asp.net自定义控件开发任我行(4)-ViewState保存控件状态
- 如何在ViewState中保存和取出自己定义的类
- 【万里征程——Windows App开发】如何在多个页面间读取/保存文件【草稿】
- ios开发 之 UIPickerView控件,UI关联选择项如何处理
- 【控件篇】ViewPager+FragmentStatePagerAdapter 页面切换案例详解
- 如何自定义View视图控件案例开发(一)
- iOS开发之 滚动视图 + 页面控件(UIScrollView + UIPageControl)
- 页面瘦身之压缩viewState和保存viewState到服务器
- 如何实现点击UITableViewCell中的控件,能调用到所在的ViewController对象进行页面跳转
- 保存页面数据的场所——Hidden、ViewState、ControlState
- android开发游记:酷炫的启动页面之如何实现两个ViewPager的联动
- 保存 全局变量值 保存页面值 static Application Session Cookie ViewState Cache Hidden
- 如何让用户控件占满全部页面,silverlight用户控件开发问题
- 求助 android开发中 如果两个控件的id相同 会怎样?如何使用findviewbyid ()寻找到?
- 【万里征程——Windows App开发】如何在多个页面间读取/保存文件【草稿】
- viewstate.static,session都可以用来保存变量或对象,页面刷新也不会自动消失
- 如果你必须开发交互式页面,ViewState越大可能意味着越有本事
- 开发交互式页面,ViewState越大可能意味着越有本事
- 【Android 开发】:UI控件之 ViewPager 多页面滑动效果控件的的使用(二)
- ASP.NET控件开发学习笔记--第6回 ViewState