管理视图状态的类:StateBag
StateBag类为控件提供属性保存的功能。StateBag类被成为状态包,其所包含的内容是页面上所有控件的属性集合,这些集合在.NET中以Control.ViewState的形式被访问。
举例来说,一个TextBox在页面回发时,如何保存用户已经填写的数据?这就需要使用StateBag来保存用户输入的值,也就是保存TextBox控件的视图状态。视图状态的跟踪在再页面的OnInit方法以后。StateBag类以字典形式保存其内部控件视图,使用的结构是键/值对,再将其以隐藏字段的形式发送到浏览器。
语法定义:
public sealed class StateBag:IStateManager,IDictionary,ICollection,IEnumerable
"IStateManager"接口定义访问视图状态的一些方法,其他三个接口都用来定义与集合字典有关的方法.
使用StateBag类的构造函数有重载,其语法如下:
public StateBag(bool ignoreCase)
public StateBag()
带参数ignoreCase的构造函数,表示可以区分存储数据的大小写。在使用StateBag类的时候,通常不使用new关键字实例化此类,而是直接使用控件的ViewState属性,后者属于StateBag类的一个对象。
属性详解:
StateBag类是一个字典存储结构,所包含的属性与其他字典类相似。下面列出了这些属性及其说明:
Count:StateItem对象数量
Item:存储的项的值
Keys:项的键集合
Values:视图状态的集合
方法详解:
StateBag类的方法也是所有字典类基本具备的方法。下面列出常用的:
Add:添加项到StateBag
Clear:清空StateBag中的项
IsItemDirty:判断StateBag中项是否标记为已修改
Remove:移除指定的项
SetDirty:设置StateBag的已修改标记
SetItemDirty:设置StateBag中某项的已修改标记
下面的代码演示如何使用StateBag类中的方法:
ViewState.Add("TextValue",TextBox1.Text); //添加项
if(ViewState.IsItemDirty("TextValue")) //判断是否修改
ViewState.SetItemDirty("TextValue",true); //设置为修改状态
ViewState.Remove("TextValue"); //移除项
ViewState.Clear(); //清空视图
典型应用:在自定义控件中保存其属性
本例的目的是当前用户刷新界面时,保存控件设置的内容。现在的服务器控件都具备这种属性,本例子只是为了说明StateBag类的作用原理。
演示实例的步骤:
1、新建一个网站,命名为“StateBagSample”.
2、在App_Code目录下添加一个类,MyLabel.cs
3、在类中自定义一个控件,此控件继承Control类,只有一个属性“Text”,功能类似于一个简单的Label控件。代码如下,注意其并不保存用户属性。
/// <summary>
/// MyTextBox 的摘要说明
/// </summary>
namespace MyLabel
{
public class MyLabel : Control
{
private string text;
public string Text
{
get { return this.text; }
set { this.text = value; }
//get { return ViewState["Text"].ToString(); }
//set { ViewState["Text"] = value; }
}
public MyLabel()
{ }
protected override void Render(HtmlTextWriter writer)
{
writer.Write(this.Text);
}
}
}
4、打开Default.aspx页,在源代码视图中注册定义的控件,代码如下:
<%@ Register TagPrefix="mylbl" Namespace="MyLabel"%>
5、在源代码视图中,添加一个Button,用来刷新页面。添加自定义控件的代码如下:
<mylbl:MyLabel ID="lbl1" runat="server" Text=""></mylbl:MyLabel>
6、在Page_Load事件中输入测试代码,如下:
if(!this.IsPostBack)
lbl1.Text = "this is a test";
7、运行程序,可以看到自定义控件显示的内容,再单击Button按钮,发现自定义控件的内容消失了,这说明没有保存视图状态。
8、修改自定义控件的类“MyLabel.cs”的属性如下,再重复7步骤的测试,测试是否正常保存了控件的状态。
get { return ViewState["Text"].ToString(); }
set { ViewState["Text"] = value; }
结果:正常保存了控件的状态。
ViewState用法
ASP.NET中的ViewState是ASP.NET中用来保存WEB控件回传时状态值一种机制.在WEB窗体(FORM)的设置为runat="server",这个窗体(FORM)会被附加一个隐藏的属性_VIEWSTATE._VIEWSTATE中存放了所有控件在ViewState中的状态值.
在Control类中,ViewState是类Control中的一个域(属性),
//
// 摘要:
// 获取状态信息的字典,这些信息使您可以在同一页的多个请求间保存和还原服务器控件的视图状态。
//
// 返回结果:
// 包含服务器控件视图状态信息的 System.Web.UI.StateBag 类的实例。
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[WebSysDescription("Control_State")]
protected virtual StateBag ViewState { get; }
其他所有控件通过继承Control来获得了ViewState功能.它的类型是system.Web.UI.StateBag,一个名称/值的对象集合.
当请求某个页面时,ASP.NET把所有控件的状态序列化成一个字符串,然后做为窗体的隐藏属性送到客户端.当客户端把页面回传时,ASP.NET分析回传的窗体属性,并赋给控件对应的值.当然这些全部是由ASP.NET负责的.
定义ViewState属性
Public int PageCount
{
get{return(int)ViewState["PageCount"];}
set{ViewState["PageCount"]=value;}
}
使用ViewState的条件
如果要使用ViewState,则在ASPX页面中必须有一个服务器端窗体标记(<formrunat=server>).窗体字段是必需的,这样包含ViewState信息的隐藏字段才能回传给服务器.而且,该窗体还必须是服务器端的窗体,这样在服务器上执行该页面时,ASP.NET页面框架才能添加隐藏的字段.
Page的EnableViewState属性值为true.
控件的EnableViewState属性值为true.
提醒:
1.当存在页面回传时,不需要维持控件的值就要把ViewState禁止.
2.ViewState的索引是大小写敏感的.
3.ViewState不是跨页面的.
4.为了能包存在ViewState中,对象必须是可流化或者定义了TypeConverter.
5.控件TextBox的TextMode属性设置为Password时,它的状态将不会被保存在ViewState中,这应该是出于安全性的考虑.
6.在页面没有回传或重定向或在回传中转到(transfer)其他页面时不要使用ViewState.
7.在动态建立控件时要小心它的ViewState.
8.当禁止一个程序的ViewState时,这个程序的所有页面的ViewState也被禁止了.
9.只有当页面回传自身时ViewState才是持续的.
设置ViewState
ViewState可以在控件,页,程序,全局配置中设置.缺省情况下EnableViewState为true.如果要禁止所有页面ViewState功能,可以在程序配置中把EnableViewState设为false.
视图集合的项管理:StateItem
SateItem类是StateBag类的一个子集。它是视图状态中的某一项,通过此类可以判断控件的某一个属性的值是否发生变化,并获取这个值。通过StateBag类的方法“Add”能将StateItem添加到集合中,使用StateBag类的Item也能访问StateItem。
语法定义
public sealed class StateItem
在实例化StateItem的时候,通常不使用构造函数,而是直接从StateBag类的项获取,代码如下:
StateItem myItem = ViewState.Add("name","cgj");
属性详解:
StateItem类主要用来判断获取视图状态中某一项的值。其属性比较简单,只有两个:
IsDirty:判断存储的对象是否已经更改
Value:获取存储对象的值
两个属性的使用方法如下:
StateItem myItem = ViewState.Add("name","cgj");
if(myItem.IsDirty)
Response.Write(myItem.Value);
典型应用:打印当前页面的所有视图状态
当一个页面启用状态视图时,每次页面回发都会有一个隐藏字段,用来存储页面中所有的视图状态,本例通过Response、StateItem和StateBag相结合的方式,显示了当前页中的所有视图状态。本例的关键技术还有枚举的迭代,这是因为ViewState实现了接口“IEnumerable”。
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState.Add("name", "cgj");//添加一个值
}
if (IsPostBack)//回发时判断
{
Response.Write("当前页保存的视图状态主要有:<br />");
IDictionaryEnumerator mykeys = ViewState.GetEnumerator();
while (mykeys.MoveNext())
{
StateItem myitem = (StateItem)mykeys.Value;
Response.Write(myitem.Value);
}
}
}