源码:https://files.cnblogs.com/sifang2004/ControlStateDemo.rar
控件适配器开启基本控件的控件状态
前言
刚写了篇控件状态vs视图状态,那势必涉及到如何使用这个控件状态了。那就从先写下这篇随笔。这方面的资料还很少,我写的这是否有用,或者是否完全正确,也靠园子里的朋友指点一二。
基本知识
WebControlAdapter 类
Web 控件从 WebControl 基类继承。该基类定义了许多对于所有 Web 控件都通用的属性。有关更多信息,请参见 WebControl。
WebControlAdapter 对象是替换特定 WebControl 类的组件或是在其执行寿命周期中继承的方法或事件,以便能够执行特定于浏览器或特定于标记内容的处理。针对每个客户端请求,.NET Framework 将单个控件适配器映射到一个派生的 WebControl 对象。
适配器可以针对某个特定的浏览器或某一类浏览器修改控件行为,还可以作为针对某功能的任选筛选器。呈现行为中的许多适应能力都可以封装在从 HtmlTextWriter 类派生的专用类中。因此,单个适配器将可能用于许多浏览器类行为,或者 HtmlTextWriter 类中包括的适应性使得无需使用控件适配器成为可能。
控件自身并不一定需要适配器。如果控件是通过组合扩展得到的,则通常子控件的适配器已经够用。
每个控件都通过 .browser 定义文件获得对应于适配器的显式映射。因此,对 WebControl 的 Adapter 属性的任何访问都使用从 .browser 定义文件中提取的 HttpBrowserCapabilities 对象来查找适配器到控件的映射。
在处理的过程中,.NET Framework 会截获对一个可能因目标而异的控件的可重写方法的调用。如果附加了控件适配器,.NET Framework 会调用关联的适配器方法。
Pair 类
Pair 类用作存储两个相关对象的基本结构。它是在整个 ASP.NET 中(在如页面状态管理任务期间或配置节处理程序的过程中)有多种用法的实用工具类。可以在自己的代码中需要包含两个相关对象的结构的任意位置和不一定需要数据绑定的位置使用 Pair 类。Pair 类不将其对象引用 First 和 Second 封装在属性中;该类直接将它们作为公共类字段公开到所有调用代码。
Pair 类在页状态保留实现中有多种用法。最常见的用法是同时作为 ViewState 和 ControlState 集合的容器。在这种情况下,First 属性用于 ViewState,而 Second 用于 ControlState。
自定义的LableAdapter适配器
这是我为了开启System.Web.UI.WebControls.Label控件的控件状态而写的一个适配器,派生自System.Web.UI.WebControls.WebControlAdapter。其实我也摸着石头过河。而且,我写这个适配器的也并不是说很有用,只是示范一下该东西是如何使用的。
using System;
using System.Web;
using System.Web.UI;
using System.Security.Permissions;
namespace CustomerControlAdapter
{
[AspNetHostingPermission(
SecurityAction.Demand,
Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission(
SecurityAction.InheritanceDemand,
Level = AspNetHostingPermissionLevel.Minimal)]
public class LabelAdapter : System.Web.UI.WebControls.Adapters.WebControlAdapter
{
protected new System.Web.UI.WebControls.Label Control
{
get
{
return (System.Web.UI.WebControls.Label)base.Control;
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
base.Page.RegisterRequiresControlState(Control);
}
protected override void LoadAdapterControlState(object state)
{
if (state != null)
{
Pair p = state as Pair;
if (p != null)
{
base.LoadAdapterControlState(p.First);
Control.Text = Convert.ToString((Convert.ToInt32(p.Second)+1));
}
else
{
if (state is string)
{
Control.Text = Convert.ToString((Convert.ToInt32(state) + 1));
}
else
{
base.LoadAdapterControlState(state);
}
}
}
}
protected override object SaveAdapterControlState()
{
object obj = base.SaveAdapterControlState();
if (Control.Text != "")
{
if (obj != null)
{
return new Pair(obj, Control.Text);
}
else
{
return (Control.Text);
}
}
else
{
return obj;
}
}
}
}
代码分析
Ø 因为我的这个适配器是控制Label,所以这里返回一个强类型的Label控件
protected new System.Web.UI.WebControls.Label Control
{
get
{
return (System.Web.UI.WebControls.Label)base.Control;
}
}
Ø 因为ControlState是自定义持久机制,所以,需要重写SaveAdapterControlState()和LoadAdapterControlState(object state)这两个方法。注意,我这里只实现保持了Label的Text属性,所以,如果ForeColor等属性是没有保持的,这就是说,如果你在某次提交页面时,既改变了Label的Text属性,又改变了Label的ForeColor属性,那ForeColor是不能被保持的。
Ø 如果你想在其它地方(如SQL Server)中保持Label的状态,也应该在上述两个方法中实现。
还必需在程序的根目录中的App_Browsers文件夹中有一个.browser文件,其实你在程序中建立.browser文件时,那个App_Browsers文件夹是自动生成的。
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.WebControls.Label"
adapterType="CustomerControlAdapter.LabelAdapter" />
</controlAdapters>
</browser>
</browsers>
说明:本文与控件状态vs视图状态共用演示代码!!