在禁用视图状态的情况下仍然使用ViewState对象

在禁用视图状态的情况下仍然使用ViewState对象

本文节选自《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》一书


        当开发人员禁用了页面或控件视图状态时。控件开发人员一般在无奈情况下会使用控件状态,要重写LoadControlState,SaveControlState,还有一个OnInit方法,这样固然完全可以实现控件重要数据的控件状态数据保存。但一般LoadControlState和SaveControlState方法都要开发人员自定义编程,比较麻烦,更适合对控件中复杂的自定义类型数据进行对象序列化操作,比如一些简单的类型如:string,int,bool,color,datetime,byte,arraylist等如果是控件重要属性的话,也都挤到LoadControlState 和 SaveControlState方法中,则会显得比较啰唆。
想一下,如果页面视图没有禁用时该多好,可以以this.ViewState["Text"]的格式直接使用Control中的ViewState对象,非常方便。既然ViewState对象不管禁用还是不禁用都在Control类中是存在的,那不用它岂不浪费。这一节主要内容就是如何实现在禁用视图状态下仍然可以使用ViewState对象。
该功能在主控件ControlStateControl中已经实现了。回顾一下主控件的代码片段:
/// <summary>
/// 获得本书更多内容,请看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </summary>
public class ControlStateControl : WebControl
{
    //… …
    [Description("使用ViewState属性来存储数据此属性")]
    public string Text_ViewState
    {
        get
        {
            String s = (String)ViewState["Text_ViewState"];
            return ((s == null) ? String.Empty : s);

        }

        set
        {
            ViewState["Text_ViewState"] = value;
        }
    }
    //… …
    protected override object SaveControlState()
    {
        Pair p = new Pair();
        p.First = base.SaveViewState();
        p.Second = ((IStateManager)FaceStyle).SaveViewState();
        //… …
        return p;
    }

    protected override void LoadControlState(object savedState)
    {
        if (savedState == null)
        {
            base.LoadViewState(null);
            return;
        }
        else
        {
            //… …
            base.LoadViewState(p.First);
            //… …
        }
    }
    //… …
}
在ControlStateControl中,属性Text_ViewState仍然存储在基类Control的ViewState对象中,且运行页面中同时禁用了页面和控件视图状态,但该属性仍然能够正确地应用视图状态。
在视图状态启用状态下,在LoadViewState方法中会默认调用基类的base.LoadViewState方法,其中就包含对基类中ViewState对象进行对象序列化的代码,如下:
protected virtual void LoadViewState(object savedState)
{
    if (savedState != null)
    {
        this.ViewState.LoadViewState(savedState);
        object obj2 = this.ViewState["Visible"];
        if (obj2 != null)
        {
            if (!((bool)obj2))
            {
                this.flags.Set(0x10);
            }
            else
            {
                this.flags.Clear(0x10);
            }
            this.flags.Set(0x20);
        }
    }
}
其中这句this.ViewState.LoadViewState(savedState)为关键语句,还记得ViewState属性实际的类型为StateBag类,它是系统定义的类型视图状态实现类(我们在6.2.3小节探讨过)。
同样在,SaveViewState方法中也有序列化保存ViewState属性对象的代码,如下所示:
protected virtual object SaveViewState()
{
    if (this.flags[0x20])
    {
        this.ViewState["Visible"] = !this.flags[0x10];
    }
    if (this._viewState != null)
    {
        return this._viewState.SaveViewState();
    }
    return null;
}
关键语句为this._viewState.SaveViewState(),ViewState是对外属性,其操作的变量就是StateBag类型的_viewState。
在视图状态被禁用的情况下,由于LoadViewState和SaveViewState不再被页框架调用(默认情况下是base.SaveViewState和base.LoadViewState方法不会再被调用),所以ViewState属性功能也就失效。
了解了ViewState对象的来龙去脉,现在就讲解一下在ControlStateControl控件中仍然可以使用ViewState的原因。在LoadControlState和SaveControlState方法中分别调用base.LoadViewState和base.SaveControlState,我们可以手动调用ViewState属性对象的对象正反序列化过程。归根到底,也就是说开发人员所谓的禁用视图实际上是禁止LoadViewState和SaveViewState两个方法的执行,但理论上我们只要启动控件状态,并把这两个方法的逻辑放到LoadControlState和SaveControlState中,仍然可以利用ViewState。
本节内容有些乖张,违反了ASP.NET设计页面状态的规则。既然ASP.NET框架把视图和控件状态已经分开了,建议在实际开发中分开处理,不要滥用。在LoadControlState方法中尽量只写控件状态相关逻辑,在LoadViewState中只写视图状态相关逻辑,毕竟ControlState是专门为存储控件必需的少量数据设计的。不过上面在ControlState中使用ViewState的确是非常方便的,在处理基本类型的属性时能够节省开发时间。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值