控件状态与视图状态示例
此示例演示如何创建一个名为 IndexButton 的自定义控件,该控件使用控件状态在多个页请求间维护关键状态信息。在 ASP.net 2.0 版中引入的控件状态与视图状态类似,但功能上独立于视图状态。
网页开发人员可能会出于性能原因而禁用整个页面或单个控件的视图状态,但他们不能禁用控件状态。控件状态是专为存储控件的重要数据(如一个页面控件的页数)而设计的,回发时必须用到这些数据才能使控件正常工作(即便禁用视图状态也不受影响)。默认情况下,ASP.NET 页框架将控件状态存储在页的一个隐藏元素中,视图状态也同样存储在此隐藏元素中。即使禁用视图状态,或是使用 Session 管理状态时,页面中的控件状态仍会传输至客户端,然后返回到服务器。在回发时,ASP.NET 会对隐藏元素的内容进行反序列化,并将控件状态加载到每个注册过控件状态的控件中。
此示例阐释了一个同时在控件状态和视图状态中保存状态的自定义控件。在此示例中,IndexButton 控件派生自 Button 类,还定义了一个 Index 属性,并将该属性保存在控件状态中。为了进行比较,IndexButton 还定义了一个 IndexInViewState 属性,该属性存储在 ViewState 字典中。为了了解控件状态和视图状态之间的差异,请使用本文附带的程序来演示 IndexButton 控件。
IndexButton控件
源码 using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CustomerControls
{
[
AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
ToolboxData("<{0}:IndexButton runat=\"server\"> </{0}:IndexButton>")
]
public class IndexButton : Button
{
private int indexValue;
[
Bindable(true),
Category("Behavior"),
DefaultValue(0),
Description("The index stored in control state.")
]
public int Index
{
get
{
return indexValue;
}
set
{
indexValue = value;
}
}
[
Bindable(true),
Category("Behavior"),
DefaultValue(0),
Description("The index stored in view state.")
]
public int IndexInViewState
{
get
{
object obj = ViewState["IndexInViewState"];
return (obj == null) ? 0 : (int)obj;
}
set
{
ViewState["IndexInViewState"] = value;
}
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
Page.ReGISterRequiresControlState(this);
}
protected override object SaveControlState()
{
//调用基类的方法,从基类得到控件状态的基值
//如果indexValue不等于并且基类的控件状态不为null
//使用Pair作为便利的数据结构来高效保存(和在LoadControlState方法中还原)
//由两部分组成的控件状态
object obj = base.SaveControlState();
if (indexValue != 0)
{
if (obj != null)
{
return new Pair(obj, indexValue);
}
else
{
return (indexValue);
}
}
else
{
return obj;
}
}
protected override void LoadControlState(object state)
{
if (state != null)
{
Pair p = state as Pair;
if (p != null)
{
base.LoadControlState(p.First);
indexValue = (int)p.Second;
}
else
{
if (state is int)
{
indexValue = (int)state;
}
else
{
base.LoadControlState(state);
}
}
}
}
}
}
代码讨论
IndexButton 控件的实现阐释了三个任务,必须执行这三个任务才能使控件参与控件状态:
· 重写 OnInit 方法并调用 RegisterRequiresControlState 方法向页面注册,以参与控件状态。必须针对每个请求完成此任务。
· 重写 SaveControlState 方法,以在控件状态中保存数据。
· 重写 LoadControlState 方法,以从控件状态加载数据。此方法调用基类方法,并获取基类对控件状态的基值。如果 indexValue 字段不为零,而且基类的控件状态也不为空,Pair 类便可作为方便的数据结构使用,用来保存和还原由两部分组成的控件状态。
做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。