自定义控件的构建(5)
在ASP.NET框架中支持在回传中保存值的有2种方式:视图状态和控件状态
视图状态
ASP.NET中几个对象属性与控件最为密切的,就是ViewState了。
这里对其做下说明,任何可序列化类的实例均可添加到视图状态中,但是实际上,如果添加到名为_ViewState的隐藏表单域变的太大,会影响页面执行效率。
下面定义的控件包含了Text和ViewStateText属性,只有后者使用视图状态,那么ViewStateText属性的值会在页面回传中保存。
namespace ViewStateControl
{/// <summary>
///支持视图状态
/// </summary>
public class SupportViewStateControls : WebControl{public string Text{get;
set;
}public string ViewStateText{get
{if (ViewState["ViewStateText"] == null)return String.Empty;
else
return (string)ViewState["ViewStateText"];}set
{ViewState["ViewStateText"] = value;}}protected override void RenderContents(HtmlTextWriter writer){writer.Write("Text:" + Text);
writer.WriteBreak();writer.Write("ViewStateText:" + ViewStateText);
writer.WriteBreak();}}}
上面的代码中ViewStateText属性使用了Control类的ViewState集合在页面回传中保持并赋给ViewStateText属性的值。
在添加一个值到ViewState集合中时,其会自动填充至_VIEWSTATE隐藏表单域
Tip:因为视图状态在页面的InitComplete()后加载,在PreRenderComplete()后保存,也就是说不能在InitComplete()之前检索视图状态或者PreRenderComplete()后添加值至视图状态
控件状态
之所以在ASP.NET中引入控件概念,即使在视图状态被禁用时,仍可以用控件状态将信息保存在_VIEWSTATE隐藏表单域中
这句话很费解,举例来说明:一个GridView中包含了500条记录,为了改善性能,我们可以禁用视图状态,防止其将这些数据填充到_VIEWSTATE域里,
但是对于当前页数及选中的记录,我们仍希望GridView记住这些信息,这时就用到了控件状态。
namespace ViewStateControl
{/// <summary>
///支持控件状态
/// </summary>
public class SupportControlStateControls : WebControl{public string ViewStateText{get
{if (ViewState["ViewStateText"] == null)return String.Empty;
else
return (string)ViewState["ViewStateText"];}set
{ViewState["ViewStateText"] = value;}}private string _controlStateText;public string ControlStateText{get
{return _controlStateText;
}set
{_controlStateText = value;
}}protected override void OnInit(EventArgs e){Page.RegisterRequiresControlState(this);
base.OnInit(e);
}protected override object SaveControlState(){return _controlStateText;
}protected override void LoadControlState(object savedState){_controlStateText = (string)savedState;
}protected override void RenderContents(HtmlTextWriter writer){writer.Write("ViewStateText:" +ViewStateText);
writer.WriteBreak();writer.Write("ControlStateText:" + ViewStateText);
writer.WriteBreak();}}}
这个代码用ViewStateText表示视图状态,ControlStateText属性表示控件状态,在OnInit()中RegisterRequiresControlState方法被调用指定该控件需要利用控件状态。SaveControlState和LoadControlState事件负责保存加载控件状态。
运行
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TestStateControl.aspx.cs" Inherits="TestViewStateControl" %>
<%@ Register TagPrefix="states" Namespace="ViewStateControl" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head runat="server"><title></title></head><body><form id="form1" runat="server"><div><states:SupportControlStateControls ID="SupportControlStateControls1" EnableViewState="false" runat="server" /><asp:Button ID="Button1" runat="server" Text="Button" /></div></form></body></html>
后台代码:
因为EnableViewState属性被关闭,所以单击按钮时,只有ControlStateText的属性值不会丢失protected void Page_Load(object sender, EventArgs e){if (!IsPostBack)
{SupportControlStateControls1.ViewStateText = "Hello";
SupportControlStateControls1.ControlStateText = "Hello";
}}
本文参考了《ASP.NET 3.5 揭秘(卷2)》