■ 葛玲是谁? - 服务器控件的状态保持
若干年前有一个火腿肠广告,对话如下:
吕丽萍:冬宝,在想啥呢?
葛 优:想葛玲
吕丽萍:别想了,我给你介绍一位新朋友--DUDU牌火腿肠
吕丽萍:(过一会儿)还想葛玲吗?
葛 优:葛玲是谁?
人机交互设计的一个重要内容是交互工作流,而实现交互工作流的前提是状态保持,否则就会出现"葛玲是谁"这样的幽默。
控件可以利用传统的cookies、session、隐藏控件等方法来存储状态值,在《随想八》中我们已经探讨过视图状态(ViewState)的作用和原理,本质上,ASP.NET创造出的有状态、连续的页面状态保持机制是通过页面隐藏数据。接下来我们通过改造上例进一步研究利用视图状态来完成控件状态保持的细节。
// MyControls.cs 自定义控件集
……
public class MyFirstControl:Control{ //输出属性Number绝对值控件
private int _number;
public int Number{……}
//增加属性NumberInViewState,用以存取属性Number的视图状态值
public int NumberInViewState{
get{
object o = ViewState["NumberInViewState"];
return (o==null)?0:(int)o;
}
set { ViewState["NumberInViewState"]=value; }
}
protected override void Render(HtmlTextWriter writer){……}
}
……
// TestMyControls.aspx页面文件
<html>
……
<%@ Page Language="C#" %>
<script runat="server">
protected override void OnLoad(EventArgs e)
{
test1.NumberInViewState--; //视图状态相应值自减1
test1.Number = test1.NumberInViewState; //自定义控件值与视图值保持一致
base.OnLoad(e);
}
</script>
<form runat="server">
<mc:MyFirstControl id="test1" runat="server" />
<input type="submit" />
</form></body></html>
■ 换杯子还是换粉圆? - 控件树与服务器控件的生命周期
在运行期,页面框架会在杯子里放入指定的服务器控件类实例,当然它们不是胡乱堆积在一块,而是组合成一颗控件树,图10-2为例2页面的控件树模型,我们可以通过控件的ID或在树中的位置控制控件,也可以增加或删除控件。
在假想的有状态、连续的页面前提,意味着在初始请求后,页面必须保存每一个控件的状态,在回传(PostBack)后,首先是恢复控件原来的状态,再处理新的请求。也就是说,每一个客户端对同一个页面的连续N次请求,相当于向奶茶铺连续要了N杯同一品种的奶茶,第一杯珍珠奶茶中粉圆状态是默认的,从顾客提出第二杯奶茶请求起,伙计必须先把这杯中粉圆状态拨弄成与端给顾客时的上一杯状态一模一样,然后根据顾客新的事件进行调整。如图10-2。详细过程请查阅MSDN的《控件执行生命周期》。

一个很自然的想法是为什么对每一次请求我们都要把整个杯子换掉呢?如果仅仅是换掉几个粉圆和一小部份奶茶,将大大改善系统性能,这就是Ajax技术的出发点。
