【原创】ASP.NET学习(3)

Abstract:

通过一个简单的 web application, 学习以下内容:

(1) ListView control

(2) User control

(3) Handle ViewState in User control

(4) FindControl() usage, especially when there is a Master page.

本文主要讲述第3部分,如何在User Control 里面处理ViewState

上一篇中提到用User Control PassRateProgressBar 来显示每个学生的及格率。表面上看,一切都好。但是当页面Postback的时候,可以看到ProgressBar被“清零”了!

先在页面加上一个ASP:Buttton 服务器端控件,什么也不做。 但是因为这是个Server端控件,每次点击会触发页面的Postback,看看会出现什么效果。

QQ截图未命名

当点击Button时,发生了Postback,这个时候页面显示如下:

QQ截图未命名2

进度条的数据“丢失”了!

为啥偏偏PassRate的数据丢失了呢? 肯定是因为在页面Postback的时候,这部分数据没有被Server端接收到,从而在页面再返回给Client端的时候,这部分信息就显示不出来了。

我们知道ASP.NET是借助于ViewState保存Server端控件的状态信息,从而在页面的Postback的过程中这些状态不会被丢失。而且默认Server端控件都是支持ViewState的. 为啥自己定义的Server端控件状态信息丢失了,没有被保存呢?

原来ASP.NET对user control中的状态信息,并没有自动加到ViewState里面,因为ViewState会增加页面的数据传输量,影响页面的响应时间,因为从性能角度考虑ASP.NET默认并不会为自定义的服务器控件的状态信息保存在ViewState中,需要自己去实现这部分操作。

那么,该如何把用户定义的服务器端的控件中的相关信息保存在ViewState中,使得其表现行为跟内建的服务器端控件一致呢? 首先,我们需要了解ViewState的机理和它的生命周期。具体内容可以参考MSDN Understanding ASP.NET ViewState http://msdn.microsoft.com/en-us/library/ms972976.aspx 或者 读书笔记 

(1) Disable ListView’s ViewState

在讲如何让自定义控件保留住状态信息,先考虑下如果把这个ListView的属性 EnableViewState设置成“FALSE”,结果会怎样? 可以想见,如果ListView的ViewState被disable了,那么页面每次Postback时,这个ListView都会重新Bind数据,从而PassRateProgressbar的Percentage数据也会被重新Bind,因此进度条每次都能够 正常 显示! 所以,解决这个问题最简单的方法就是disable ListView的ViewState! 这样做的坏处当然也是显而易见的,这样页面每次postback都需要进行数据的Bind,如果数据是从数据库中获取的,数据量很大的话,可想而知对性能的影响还是很大的。

(2) Implement LoadViewState in User Control

因此,我们应该转向让自定义的控件实现ViewState机制。了解ASP.NET页面周期的话,就会知道在Page_Load之前有个很重要的过程叫LoadViewState, 这个方法是定义在control类中。这个方法只会在页面PostBack的时候才会被调用,在页面以一次Load的时候不会被执行。

LoadViewState方法的作用,就是从上一个页面中ViewState保存的状态信息取出来,然后赋值给准备响应页面请求的页面中相关控件的状态属性。从而,在页面返回给Client时,这些状态信息不会发生变化。

所以,首先我们需要给PassRateProgressBar中实现这个方法,从中取得我们需要的Percentage的信息,

   1: protected override void LoadViewState(object savedState)
   2: {
   3:    if (savedState != null)
   4:    {
   5:        base.LoadViewState(savedState);
   6:        string aPercent = (string)ViewState["percentage"];
   7:        if (aPercent != null)
   8:        {
   9:            Percentage = aPercent;
  10:        }
  11:    }
  12: }

注意:

base.LoadViewState(savedState);

这句代码是必需的,否则不会work!

疑问 1:

保存程序, Debug下,但是发现在页面Postback的时候,这个方法并没有被执行!! 这个很奇怪,居然没有被执行! (好像只有在实现了(override) 方法SaveViewState之后,才会执行LoadViewState!)

为了证实这一想法,可以把Percentage的Setter/Getter改成默认形式(不实现),覆写(override) 方法SaveViewState, 发现在page postback的时候会执行LoadViewState方法!

回过头来,改变下属性Percentage的Setter/Getter...

   1: public string Percentage
   2: {
   3:     get;
   4:     set;
   5: }

===>

   1: public string Percentage
   2: {
   3:    get
   4:    {
   5:       return (string)ViewState["percentage"] ?? string.Empty;
   6:    }
   7:  
   8:    set
   9:    {
  10:        ViewState["percentage"] = value;
  11:    }
  12: }

再重新Debug下,这次发现在页面Postback的时候, LoadViewState方法被执行了!!!

疑问2:

我并没有实现SaveViewState方法, 但是却能work!  也许只需要实现了Percentage的Setter/Getter (已经往ViewState里面存储状态信息了)即可。

Conclusion:

(1) Decide when to disable ViewState is important.

(2) Remember to implement LoadViewState() for the user control

-- To Be Continued--

原文地址:https://www.cnblogs.com/fangwenyu/p/1594006.html