扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:中国IT实验室 来源:中国IT实验室 2007年9月7日
关键字: ASP.NET
在前面的系列文章中,我们曾经介绍了视图状态和控件状态的基本概念和典型应用,从中可以发现,视图状态和控件状态对于自定义服务器控件实现的重要性。本文将继续这一主题,重点介绍实现视图状态和控件状态自定义管理的方法。
自定义视图状态管理
在介绍视图状态时,我们曾经提到过:对于简单属性,例如,String、Int等类型,.NET执行引擎将自动启用默认视图状态管理机制,以便完成相应的功能。然而,如果开发人员在ViewState中保存的是自定义数据类型,或者需要实现自定义方式优化视图状态管理时,则必须实现自定义视图状态管理。
实现自定义视图状态管理可以通过两种方法。方法一:实现System.Web.UI命名空间中的IStateManager接口成员,其中包括IsTrackingViewState属性和TrackViewState、SaveViewState和LoadViewState方法。这种方法主要是针对自定义数据类型的视图状态管理的情况。方法二:重写Control基类的3个视图状态管理方法:TrackViewState、SaveViewState和LoadViewState。这些方法与IStateManager接口定义的3个方法名称一致。这种方法主要用于通过自定义方式优化默认视图状态管理的情况,其主要目的在于提高效率和性能。掌握以上两种实现方法的捷径是,必须深刻理解.NET框架内部实现视图状态管理的过程。下面两小节内容都是有关内部实现方法的介绍。每一节中均有实现代码,实际就相当于实例代码。所有服务器控件的自定义视图状态管理的实现都不会偏离那些代码所表达的逻辑。当读者真正掌握了那些内部实现方法,那么自定义视图状态管理的实现方法也就迎刃而解了。
1、实现基于IStateManager接口的自定义视图状态管理
对于复杂属性而言,多数需要实现自定义视图状态管理,其关键是实现System.Web.UI.IStateManager接口中定义的方法和属性。下面列举了IStateManager接口定义代码。public interface IStateManager{ bool IsTrackingViewState {get;} void LoadViewState(object state); object SaveViewState(); void TrackViewState();}
如上代码所示,IStateManager接口要求类实现IsTrackingViewState属性,以及LoadViewState、SaveViewState和TrackViewState方法。IsTrackingViewState属性定义,当由类实现时,获取一个布尔值,通过该值指示服务器控件是否正在跟踪其视图状态更改。如果服务器控件正在跟踪其视图状态更改,则为true;否则为false。SaveViewState方法定义,当由类实现时,将服务器控件的视图状态更改保存到Object中。LoadViewState方法定义,当由类实现时,加载服务器控件以前保存的控件视图状态,其中的参数state表示包含控件保存的视图状态值的Object。TrackViewState方法定义,当由类实现时,指示服务器控件跟踪其视图状态更改。
ViewState属性与IStateManager接口之间存在密切联系。ViewState属性的类型是StateBag类,StateBag类通过实现IStateManager接口中定义的方法和属性来参与状态管理。其实现过程如下。public sealed class StateBag : IStateManager, IDictionary,ICollection, IEnumerable{
private bool _isTrackingViewState;
private ArrayList _keys;
private ArrayList _values;
private StateItem _item;
bool IStateManager.IsTrackingViewState {
get { return _isTrackingViewState; }
}
void IStateManager.TrackViewState() {
_isTrackingViewState = true;
}
object IStateManager.SaveViewState() {
_keys = new ArrayList();
_values = new ArrayList();
IDictionaryEnumerator myDirctionaryEnumerator = this.GetEnumerator();
while(myDictionaryEnumerator.MoveNext()) {
if(this.Item[(String)myDictionaryEnumerator.Key].IsDirty) {
_keys.Add(myDictionaryEnumerator.Key);
_values.Add(myDictionaryEnumerator.Value);
}
}
if(_keys.Count>0) {
return new Pair(_keys,_values);
}
}
void IStateManager.LoadViewState(object savedState) {
if(savedState is Pair) {
_keys = (ArrayList)tempP.First;
_values = (ArrayList)tempP.Second;
IDictionaryEnumerator myDirctionaryEnumerator = this.GetEnumerator();
while(myDictionaryEnumerator.MoveNext()) {
for(int j=0;j<_keys.Count;j++)
{
if((String)myDictionaryEnumerator.Key == _keys[j].ToString());
{
this.Item[_keys[j].ToString()].Value = (object)_values[j];
}
}
}
}
}
}
请读者注意:以上代码为示意性代码,并非严格意义上的实现代码。在此列出,主要是用于说明StateBag类实现IStateManager接口的逻辑过程。
通过上面的代码,我们可以看到:
(1)在IsTrackingViewState属性中,将该属性设置为只读,并且使用私有变量_isTrackingViewState。
(2)在TrackViewState方法中,把IsTrackingViewState属性使用的私有变量_isTrackingViewState设置为true,这指示系统当某个StateItem添加到StateBag中,或者某个StateItem值被修改时,StateBag类就会自动将该StateItem标记为修改过即添加dirty标记。
(3)在SaveViewState方法中,循环StateBag中的每个StateItem,如果该StateItem被标记为dirty,那么就将其键和值分别添加到两个ArrayList中,并返回该对象。
(4)在LoadViewState方法中,执行了与SaveViewState方法相反的操作。首先将savedState对象分解为两个保存有键和值的ArrayList,然后将其中的值加载到相应的StateItem对象中。
以上就是ViewState属性实现IStateManager接口的基本过程。所有的视图状态管理过程,都要使用以上的实现过程,因此理解以上逻辑对于深入掌握自定义视图状态管理机制具有举足轻重的作用。
在前面的系列文章中,我们曾经介绍了视图状态和控件状态的基本概念和典型应用,从中可以发现,视图状态和控件状态对于自定义服务器控件实现的重要性。本文将继续这一主题,重点介绍实现视图状态和控件状态自定义管理的方法。
自定义视图状态管理
在介绍视图状态时,我们曾经提到过:对于简单属性,例如,String、Int等类型,.NET执行引擎将自动启用默认视图状态管理机制,以便完成相应的功能。然而,如果开发人员在ViewState中保存的是自定义数据类型,或者需要实现自定义方式优化视图状态管理时,则必须实现自定义视图状态管理。
实现自定义视图状态管理可以通过两种方法。方法一:实现System.Web.UI命名空间中的IStateManager接口成员,其中包括IsTrackingViewState属性和TrackViewState、SaveViewState和LoadViewState方法。这种方法主要是针对自定义数据类型的视图状态管理的情况。方法二:重写Control基类的3个视图状态管理方法:TrackViewState、SaveViewState和LoadViewState。这些方法与IStateManager接口定义的3个方法名称一致。这种方法主要用于通过自定义方式优化默认视图状态管理的情况,其主要目的在于提高效率和性能。掌握以上两种实现方法的捷径是,必须深刻理解.NET框架内部实现视图状态管理的过程。下面两小节内容都是有关内部实现方法的介绍。每一节中均有实现代码,实际就相当于实例代码。所有服务器控件的自定义视图状态管理的实现都不会偏离那些代码所表达的逻辑。当读者真正掌握了那些内部实现方法,那么自定义视图状态管理的实现方法也就迎刃而解了。
1、实现基于IStateManager接口的自定义视图状态管理
对于复杂属性而言,多数需要实现自定义视图状态管理,其关键是实现System.Web.UI.IStateManager接口中定义的方法和属性。下面列举了IStateManager接口定义代码。public interface IStateManager{ bool IsTrackingViewState {get;} void LoadViewState(object state); object SaveViewState(); void TrackViewState();}
如上代码所示,IStateManager接口要求类实现IsTrackingViewState属性,以及LoadViewState、SaveViewState和TrackViewState方法。IsTrackingViewState属性定义,当由类实现时,获取一个布尔值,通过该值指示服务器控件是否正在跟踪其视图状态更改。如果服务器控件正在跟踪其视图状态更改,则为true;否则为false。SaveViewState方法定义,当由类实现时,将服务器控件的视图状态更改保存到Object中。LoadViewState方法定义,当由类实现时,加载服务器控件以前保存的控件视图状态,其中的参数state表示包含控件保存的视图状态值的Object。TrackViewState方法定义,当由类实现时,指示服务器控件跟踪其视图状态更改。
ViewState属性与IStateManager接口之间存在密切联系。ViewState属性的类型是StateBag类,StateBag类通过实现IStateManager接口中定义的方法和属性来参与状态管理。其实现过程如下。public sealed class StateBag : IStateManager, IDictionary,ICollection, IEnumerable{
private bool _isTrackingViewState;
private ArrayList _keys;
private ArrayList _values;
private StateItem _item;
bool IStateManager.IsTrackingViewState {
get { return _isTrackingViewState; }
}
void IStateManager.TrackViewState() {
_isTrackingViewState = true;
}
object IStateManager.SaveViewState() {
_keys = new ArrayList();
_values = new ArrayList();
IDictionaryEnumerator myDirctionaryEnumerator = this.GetEnumerator();
while(myDictionaryEnumerator.MoveNext()) {
if(this.Item[(String)myDictionaryEnumerator.Key].IsDirty) {
_keys.Add(myDictionaryEnumerator.Key);
_values.Add(myDictionaryEnumerator.Value);
}
}
if(_keys.Count>0) {
return new Pair(_keys,_values);
}
}
void IStateManager.LoadViewState(object savedState) {
if(savedState is Pair) {
_keys = (ArrayList)tempP.First;
_values = (ArrayList)tempP.Second;
IDictionaryEnumerator myDirctionaryEnumerator = this.GetEnumerator();
while(myDictionaryEnumerator.MoveNext()) {
for(int j=0;j<_keys.Count;j++)
{
if((String)myDictionaryEnumerator.Key == _keys[j].ToString());
{
this.Item[_keys[j].ToString()].Value = (object)_values[j];
}
}
}
}
}
}
请读者注意:以上代码为示意性代码,并非严格意义上的实现代码。在此列出,主要是用于说明StateBag类实现IStateManager接口的逻辑过程。
通过上面的代码,我们可以看到:
(1)在IsTrackingViewState属性中,将该属性设置为只读,并且使用私有变量_isTrackingViewState。
(2)在TrackViewState方法中,把IsTrackingViewState属性使用的私有变量_isTrackingViewState设置为true,这指示系统当某个StateItem添加到StateBag中,或者某个StateItem值被修改时,StateBag类就会自动将该StateItem标记为修改过即添加dirty标记。
(3)在SaveViewState方法中,循环StateBag中的每个StateItem,如果该StateItem被标记为dirty,那么就将其键和值分别添加到两个ArrayList中,并返回该对象。
(4)在LoadViewState方法中,执行了与SaveViewState方法相反的操作。首先将savedState对象分解为两个保存有键和值的ArrayList,然后将其中的值加载到相应的StateItem对象中。
以上就是ViewState属性实现IStateManager接口的基本过程。所有的视图状态管理过程,都要使用以上的实现过程,因此理解以上逻辑对于深入掌握自定义视图状态管理机制具有举足轻重的作用。
自定义控件状态管理
视图状态与控件状态在数据管理方面不太相同。ASP.NET 2.0在支持针对简单属性的默认视图状态管理机制的同时,还支持自定义视图状态管理。然而,对于控件状态管理而言,则不存在默认控件状态管理机制。开发人员必须实现自定义控件状态管理过程。本小节介绍一下自定义控件状态管理的实现方法,这对于实现基于控件状态功能的对象有着重要意义。
实际上,在前面系列文章介绍控件状态的过程中,读者已经接触了控件状态实现的内容,其中就包括自定义控件状态管理的实现。这个过程的实现与基于Control基类的自定义视图状态管理非常相似,二者都需要重写Control基类中的方法。实现自定义控件状态管理需要重写Control基类的SaveControlState和LoadControlState。下面列举了一段简单示例代码。public class Sample : Control {
private int currentIndex = 0;
protected override void OnInit(EventArgs e) {
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
protected override object SaveControlState() {
return currentIndex != 0 ? (object)currentIndex : null;
}
protected override void LoadControlState(object state) {
if (state != null) { currentIndex = (int)state; }
}
}
实现自定义控件状态管理分为3个关键步骤:
(1)调用RegisterRequiresControlState方法。该方法用于将自定义控件注册为具有持久性控件状态的控件。
(2)重写SaveControlState方法。该方法用于保存自页回发到服务器后发生的任何服务器控件状态更改。
(3)重写LoadControlState方法。该方法用于从SaveControlState方法保存的上一个页请求还原控件状态信息。
小结
本章主要介绍了自定义视图状态和控件状态管理的内容。它们对于实现自定义服务器控件有着重要意义。建议读者首先深入理解理论知识,然后再尝试进行开发工作,这样可获得更好的学习效果。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者