ASP.NET2.0服务器控件之自定义状态管理

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接口的基本过程。所有的视图状态管理过程,都要使用以上的实现过程,因此理解以上逻辑对于深入掌握自定义视图状态管理机制具有举足轻重的作用。

  2、实现基于Control基类的自定义视图状态管理

  如果开发人员需要优化默认视图状态管理机制,以提高控件运行效率和性能,那么必须理解Control基类中默认视图状态管理机制。通过掌握这个管理机制,可以模仿其处理过程以实现自定义视图状态管理。

  实现基于Control基类的自定义视图状态管理,需要开发人员实现3个方法:LoadViewState、SaveViewState和TrackViewState。它们与上一小节中介绍的IStateManager接口成员方法同名,并且在方法意义上也基本相同。在此就不对这3个方法多做说明了。

  Control基类中的默认视图状态管理机制定义了一个StateBag类型的ViewState属性,并将视图状态管理的任务委托给它。下面请看Control基类的默认状态管理的实现逻辑。

private StateBag _viewState;
protected virtual StateBag ViewState{
 get {
  if(_viewState != null)
  {
   return _viewState;
  }
  _viewState = new StateBag(ViewStateIgnoresCase);
  if(IsTrackingViewState)
   _viewState.TrackViewState();
   return _viewState;
 }
}

protected virtual void TrackViewState(){
 if(_viewState != null) {
  _viewState.TrackViewState();
 }
 return null;
}

protected virtual object SaveViewState(){
 if(_viewState != null) {
  _viewState.SaveViewState();
 }
 return null;
}
protected virtual void LoadViewState(object savedState){
 if(savedState != null) {
  ViewState.LoadViewState(savedState);
 }
}
  从上面的代码可以看出:ViewState属性是StateBag类型,当_viewState不为null时,则返回_viewState;当_viewState为null时,则初始化一个StateBag类型的变量_viewState,并判断控件是否正在跟踪其视图状态更改,如果服务器控件正在跟踪其视图状态更改,那么就调用TrackViewState方法开始状态跟踪,最后返回_viewState。另外,在TrackViewState、SaveViewState、LoadViewState方法中,均使用了StateBag类中有关视图状态管理的方法。

  在Control基类的默认视图状态管理过程中,由于定义了ViewState属性为StateBag类型,所以必然使用上文中StateBag类实现视图状态管理的逻辑。如果让Control基类实现IStateManager接口中的方法和属性,那么其实现过程必然与StateBag类实现IStateManager接口大同小异,这必然将造成重复,由此可能造成.NET框架改变IStateManager接口的访问性质。此外,在进行自定义视图状态管理的过程中,可能出现StateBag类型与Control基类的视图状态管理机制的冲突,那样就可能产生混乱。而采用目前的这种方式,无论从灵活性、继承性、可复用性,以致从编程人员的习惯上,都具有很多优点。

  自定义控件状态管理

  视图状态与控件状态在数据管理方面不太相同。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方法保存的上一个页请求还原控件状态信息。

  小结
 
  本章主要介绍了自定义视图状态和控件状态管理的内容。它们对于实现自定义服务器控件有着重要意义。建议读者首先深入理解理论知识,然后再尝试进行开发工作,这样可获得更好的学习效果。

时间: 2024-10-26 07:51:38

ASP.NET2.0服务器控件之自定义状态管理的相关文章

ASP.NET2.0服务器控件之自定义状态管理_实用技巧

     在前面的系列文章中,我们曾经介绍了视图状态和控件状态的基本概念和典型应用,从中可以发现,视图状态和控件状态对于自定义服务器控件实现的重要性.本文将继续这一主题,重点介绍实现视图状态和控件状态自定义管理的方法. 自定义视图状态管理 在介绍视图状态时,我们曾经提到过:对于简单属性,例如,String.Int等类型,.NET执行引擎将自动启用默认视图状态管理机制,以便完成相应的功能.然而,如果开发人员在ViewState中保存的是自定义数据类型,或者需要实现自定义方式优化视图状态管理时,则必

ASP.NET2.0服务器控件之创建自定义控件

asp.net|创建|服务器|控件 摘要 本文将详细讲解一个简单的自定义服务器控件的创建过程.通过这些内容,读者将了解利用Visual Studio 2005,创建和测试自定义服务器控件的基本方法. 注意:本文内容基于ASP.NET 2.0技术撰写,示例应用程序使用Visual Studio 2005进行开发. 创建一个简单的自定义服务器控件 创建自定义服务器控件的过程包括: (1)创建一个测试用Web站点应用程序: (2)为新建站点应用程序,新增一个Web控件库项目: (3)编写.编译和测试自

ASP.NET2.0服务器控件开发之实现事件

asp.net|服务器|控件|控件开发 前面几篇文章讲解了与利用ASP.NET 2.0技术创建自定义服务器控件属性有关的内容.从本文开始,包括随后的几篇文章将探讨创建自定义服务器控件事件的方法.本文重点对实现控件事件的基本概念进行介绍,这些概念对于帮助开发人员为服务器控件创建事件有着重要意义. 1. 事件基本概念 事件是当有动作发生或者状态改变时,类发出的信息或者通知.通常情况下,状态的发生或者改变由用户界面动作初始化,例如,单击按钮,或者由于其他的程序逻辑引起.产生事件的类或者说发送通知的类叫

ASP.NET2.0服务器控件之Render方法

asp.net|服务器|控件 控件呈现是指向HTTP输出流中写入标记文本的过程.服务器通过HTTP输出流向客户端发送生成的标记文本,这些文本将会通过客户端浏览器转换为可视化的元素显示出来.使用控件呈现,开发人员可以将HTML标记.脚本代码.CSS样式表等等输入到客户端浏览器.实现服务器控件呈现主要有两种方式:一是Control类的Render方法,二是WebControl的RenderContents方法.本文重点介绍使用Control类的Render方法实现控件呈现的应用. 使用HtmlTex

ASP.NET2.0服务器控件之创建复杂属性

asp.net|创建|服务器|控件 上一篇文章介绍了实现3种形式复杂属性的具体方法.为了加深读者对于这些实现方法的理解深度,本文详细讲解了一个利用ASP.NET 2.0技术创建复杂属性的示例. 1. 示例应用 本文所实现的示例很简单,其核心是通过实现自定义服务器控件的连字符形式复杂属性来说明复杂属性的实现方法,其中使用了上一篇文章中介绍的内容.示例效果图如图1所示. 图1 如图1所示,页面显示了公司所在城市.姓名.性别和职务信息.这些内容是定义服务器控件呈现的结果,其中公司所在城市由简单属性Ci

ASP.NET2.0服务器控件之类型化样式属性

asp.net|服务器|控件 上一篇文章对控件样式属性的基本概念进行了介绍,同时,还通过示例说明了重写样式属性的方法.本文重点对类型化样式属性的创建方法进行讲解. 实现类型化样式属性的方法 继承自Style类的类称为类型化样式.Style类可以由控件开发人员来扩展,创建一个自定义类型化样式,它重写或者添加Style类的属性.服务器控件也可以把自定义类型化样式作为ControlStyle属性的类型.例如,Table控件的ControlStyle属性就是TableStyle类型,该类型是扩展的Sty

ASP.NET2.0服务器控件之捕获回传事件

asp.net|服务器|控件 1. 实现捕获回传事件       如果服务器控件需要捕获来自客户端的回传事件,并想为该回传事件自定义服务器端事件处理逻辑,那么控件必须实现System.Web.UI.IPostBackEventHandler接口.下面列举了该接口定义.      public interface IPostBackEventHandler   {    void RaisePostBackEvent(string eventArgument);   }       如上代码所示,

ASP.NET2.0服务器控件之类型转换器_实用技巧

类型转换器是实现自定义服务器控件属性过程中比较重要的内容.本文将对类型转换器的基本概念和实现方法进行介绍. 1. 类型转换器基本概念 类型转换器是自定义服务器控件的辅助性功能实现.它主要用于执行从字符串表示形式到指定类型之间的双向转换.例如,以文本形式表示属性值,将用户输入的文本转换为相应数据类型等等,都应用了类型转换器. 对于多数基本数据类型(如Int32.Bool.Char.String.枚举类型等),.net框架已经为它们提供了默认的类型转换器,这些类型转换器完成从字符串到相关值的转换并执

一起谈.NET技术,ASP.NET2.0服务器控件之类型转换器

      类型转换器是实现自定义服务器控件属性过程中比较重要的内容.本文将对类型转换器的基本概念和实现方法进行介绍. 1. 类型转换器基本概念 类型转换器是自定义服务器控件的辅助性功能实现.它主要用于执行从字符串表示形式到指定类型之间的双向转换.例如,以文本形式表示属性值,将用户输入的文本转换为相应数据类型等等,都应用了类型转换器. 对于多数基本数据类型(如Int32.Bool.Char.String.枚举类型等),.NET框架已经为它们提供了默认的类型转换器,这些类型转换器完成从字符串到相关