• 1 自定义控件之状态管理


    1 状态管理概述
    Control.ViewState :状态信息的字典。ViewState为StateBag的实例。

    image     

    管理 ASP.NET 服务器控件的视图状态。

    image    

    为支持服务器控件的视图状态管理而必须实现的属性和方法。

    名称 说明
    LoadViewState 当由类实现时,加载服务器控件以前保存的控件视图状态。
    SaveViewState 当由类实现时,将服务器控件的视图状态更改保存到 Object。
    TrackViewState 当由类实现时,指示服务器控件跟踪其视图状态更改。
    IsTrackingViewState 指示服务器控件是否正在跟踪其视图状态更改。

     

    2 如何在自定义控件中实现自定义状态管理?

    重载:LoadViewState与SaveViewState

    3.1 代码

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Web;

    using System.Web.UI;

    namespace AspnetEssential.CustomerControl

    {

    /// <summary>

    /// BarGraphControl

    /// </summary>

    /// <remarks>

    /// 简单的图表控件。根据描述,值绘制图表

    /// </remarks>

    public class BarGraphControl:Control

    {

    /// <summary>

    /// 描述列表

    /// </summary>

    private List<string> _description;

    /// <summary>

    /// 值列表

    /// </summary>

    private List<int> _values;

    /// <summary>

    /// 最大值(用于计算相BarItem的相对长度,本程序为实现此功能)

    /// </summary>

    private int _max;

    /// <summary>

    /// 构造函数中初始化控件的默认值

    /// </summary>

    public BarGraphControl()

    {

    _description = new List<string>();

    _values = new List<int>();

    }

    /// <summary>

    /// 添加键值对

    /// </summary>

    /// <param name="name"></param>

    /// <param name="value"></param>

    public void AddItem(string name,int value)

    {

    _description.Add(name);

    _values.Add(value);

    if(value>_max)

    {

    _max = value;

    }

    }

    #region State Manager

    protected override object SaveViewState()

    {

    object[] vState = new object[4];

    vState[0] = base.SaveViewState();

    vState[1] = _description;

    vState[2] = _values;

    vState[3] = _max;

    return vState;

    }

    protected override void LoadViewState(object savedState)

    {

    //base.LoadViewState(savedState);

    if(savedState !=null)

    {

    object[] vState =(object[])savedState;

    if(vState[0]!=null)

    {

    base.LoadViewState(vState[0]);

    }

    if (vState[1] != null)

    {

    _description=(List<string>)vState[1];

    }

    if (vState[2] != null)

    {

    _values=(List<int>)vState[2];

    }

    if (vState[3] != null)

    {

    _max=(int)vState[3];

    }

    }

    }

    #endregion

    #region Render

    /// <summary>

    /// 呈现

    /// </summary>

    /// <param name="writer"></param>

    protected override void Render(HtmlTextWriter writer)

    {

    //base.Render(writer);

    writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);

    writer.AddAttribute(HtmlTextWriterAttribute.Bordercolor, "red");

    //单元格内容与单元格边框的距离

    writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");

    //单元格之间的距离

    writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");

    writer.RenderBeginTag(HtmlTextWriterTag.Table);

    //bar的颜色

    string color = string.Empty;

    //绘制tr,td

    for(int i=0;i<_values.Count;i++ )

    {

    //tr

    writer.RenderBeginTag(HtmlTextWriterTag.Tr);

    //td

    writer.RenderBeginTag(HtmlTextWriterTag.Td);

    writer.WriteEncodedText(_description[i]);

    writer.RenderEndTag();

    writer.RenderBeginTag(HtmlTextWriterTag.Td);

    //writer.AddAttribute(HtmlTextWriterAttribute.Width, _values[i].ToString());

    writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "blue");

    writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");

    writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px");

    color=((i % 2) == 0 ? "red" : "blue");

    writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, color);

    writer.AddStyleAttribute(HtmlTextWriterStyle.Width, _values[i].ToString()+"px");

    writer.RenderBeginTag(HtmlTextWriterTag.Div);

    writer.RenderEndTag();

    writer.RenderEndTag();

    writer.RenderEndTag();

    }

    writer.RenderEndTag();

    }

    #endregion

    }

    }

    3.2 控件使用实例

    private const int MAXCOUNT = 10;

    protected void Page_Load(object sender, EventArgs e)

    {

    if(!this.IsPostBack)

    {

    AddBarGraphValue(this.BarGraphControl1);

    }

    }

    /// <summary>

    /// 生成控件的随机数据

    /// </summary>

    /// <param name="barControl"></param>

    private void AddBarGraphValue(BarGraphControl barControl)

    {

    Random rd = null;

    for (int i = 0; i < MAXCOUNT;i++ )

    {

    rd = new Random(i);

    int currentValue= rd.Next(100);

    string title = string.Format("Item:{0}",i.ToString());

    barControl.AddItem(title, currentValue);

    }

    }

    3.3 运行说明 

        页面执行post后控件的状态仍然保留。效果如下图所示。

       image

    4 问题:不使用重载LoadViewState与SaveViewState方法,直接把_description等字段发布为存放在viewstate 的属性也应该能达到以上效果,那么什么时候使用重载方法控件的状态管理?

    4.1 实验代码

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Web;

    using System.Web.UI;

    namespace AspnetEssential.CustomerControl

    {

    /// <summary>

    /// BarGraphControl

    /// </summary>

    /// <remarks>

    /// 简单的图表控件。根据描述,值绘制图表

    /// </remarks>

    public class BarGraphControlWithViewStateProperty:Control

    {

    /// <summary>

    /// 描述列表

    /// </summary>

    private List<string> Description

    {

    get

    {

    return ViewState["_description"] as List<string>;

    }

    set

    {

    ViewState["_description"] = value;

    }

    }

    /// <summary>

    /// 值列表

    /// </summary>

    //private List<int> _values;

    private List<int> Values

    {

    get

    {

    return ViewState["_values"] as List<int>;

    }

    set

    {

    ViewState["_values"] = value;

    }

    }

    /// <summary>

    /// 最大值(用于计算相BarItem的相对长度,本程序为实现此功能)

    /// </summary>

    //private int _max;

    private int Max

    {

    get

    {

    return (int)ViewState["_max"];

    }

    set

    {

    ViewState["_max"] = value;

    }

    }

    /// <summary>

    /// 构造函数中初始化控件的默认值

    /// </summary>

    public BarGraphControlWithViewStateProperty()

    {

    ViewState["_description"] = new List<string>();

    ViewState["_values"] = new List<int>();

    ViewState["_max"] = 0;

    }

    /// <summary>

    /// 添加键值对

    /// </summary>

    /// <param name="name"></param>

    /// <param name="value"></param>

    public void AddItem(string name,int value)

    {

    Description.Add(name);

    Values.Add(value);

    if(value>Max)

    {

    Max = value;

    }

    }

    #region Render

    /// <summary>

    /// 呈现

    /// </summary>

    /// <param name="writer"></param>

    protected override void Render(HtmlTextWriter writer)

    {

    writer.Write(

    string.Format("{0} Instance hashCode:{1}",

    this.GetType().FullName,

    this.GetHashCode()

    )

    );

    //base.Render(writer);

    writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);

    writer.AddAttribute(HtmlTextWriterAttribute.Bordercolor, "red");

    //单元格内容与单元格边框的距离

    writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "0");

    //单元格之间的距离

    writer.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0");

    writer.RenderBeginTag(HtmlTextWriterTag.Table);

    //bar的颜色

    string color = string.Empty;

    //绘制tr,td

    for(int i=0;i<Values.Count;i++ )

    {

    //tr

    writer.RenderBeginTag(HtmlTextWriterTag.Tr);

    //td

    writer.RenderBeginTag(HtmlTextWriterTag.Td);

    writer.WriteEncodedText(Description[i]);

    writer.RenderEndTag();

    writer.RenderBeginTag(HtmlTextWriterTag.Td);

    //writer.AddAttribute(HtmlTextWriterAttribute.Width, _values[i].ToString());

    writer.AddStyleAttribute(HtmlTextWriterStyle.BorderColor, "blue");

    writer.AddStyleAttribute(HtmlTextWriterStyle.BorderStyle, "solid");

    writer.AddStyleAttribute(HtmlTextWriterStyle.BorderWidth, "1px");

    color=((i % 2) == 0 ? "red" : "blue");

    writer.AddStyleAttribute(HtmlTextWriterStyle.BackgroundColor, color);

    writer.AddStyleAttribute(HtmlTextWriterStyle.Width, Values[i].ToString() + "px");

    writer.RenderBeginTag(HtmlTextWriterTag.Div);

    writer.RenderEndTag();

    writer.RenderEndTag();

    writer.RenderEndTag();

    }

    writer.RenderEndTag();

    }

    #endregion

    }

    }

    4.2 BarGraphControlWithViewStateProperty 说明:

       4.2.1 此控件在form get 时生成工作正常

       image

    4.2.2 在post 时丢失状态

    image

    在页面启用 Trace='true' ,时能看到 viewstate 的值,ViewState值肯定不是完全的。

    BarGraphControlWithViewStateProperty post时的__ViewState

    image

    BarGraphControl post 时的回传数据

    image

    5 为什么BarGraphControlWithViewStateProperty 在post中,控件丢失状态???

         5.1 比较 BarGraphControl与 BarGraphWithViewStateProperty 在get时生成的__ViewState

              5.1.1BarGraphControl get时页面生成的__ViewState

        <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTQ5NzYxMjc0Nw9kFgICAw9kFgICAQ8UKwAEZDLGAgABAAAA/////

    wEAAAAAAAAABAEAAAB/U3lzdGVtLkNvbGxlY3Rpb25zLkdlbmVyaWMuTGlzdGAxW1tTeXN0ZW0uU3RyaW5nLC

    Btc2NvcmxpYiwgVmVyc2lvbj0yLjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1Yz

    U2MTkzNGUwODldXQMAAAAGX2l0ZW1zBV9zaXplCF92ZXJzaW9uBgAACAgJAgAAAAoAAAAKAAAAEQIAAAAQAAAABgMAA

    AAGSXRlbTowBgQAAAAGSXRlbToxBgUAAAAGSXRlbToyBgYAAAAGSXRlbTozBgcAAAAGSXRlbTo0BggAAAAGSXRlbTo1BgkA

    AAAGSXRlbTo2BgoAAAAGSXRlbTo3BgsAAAAGSXRlbTo4BgwAAAAGSXRlbTo5DQYLMo0CAAEAAAD/////AQAAAAAAAAAEA

    QAAAH5TeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5MaXN0YDFbW1N5c3RlbS5JbnQzMiwgbXNjb3JsaWIsIFZlcnNpb249Mi4

    wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0DAAAABl9pdGVtcwVf

    c2l6ZQhfdmVyc2lvbgcAAAgICAkCAAAACgAAAAoAAAAPAgAAABAAAAAISAAAABgAAABNAAAAHQAAAFEAAAAhAAAAVgAAAC

    YAAABaAAAAKgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsCWmRkSxJZ9hCeFbsC8EmHusO606dT97U=" />

            5.1.2 BarGraphWithViewStateProperty get时在页面生成的__ViewState

    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgKTiu/aDAKM54rGBq/KxaTPszsZuaIb9spV87cnfmhD" />

    5.2 BarGraphControl 事件执行顺序

    image

    5.3  经跟踪发现BarGraphControlWithViewStateProperty的值只有max有值,其他两个list都没有值。会不会是ViewState只能保存简单类型,不能保存复杂类型如list<int>?

    protected void Page_Load(object sender, EventArgs e)

    {

    if(!IsPostBack )

    {

    SaveViewStateInfo();

    }

    ShowViewStateInfo();

    }

    private void SaveViewStateInfo()

    {

    this.ViewState["max"] = 100;

    this.ViewState["list"] = new List<int>() { 1,2,3};

    Dictionary<string, int> myDic =

    new Dictionary<string, int>()

    {

    {"hb1",100},

    };

    this.ViewState["dic"] = myDic;

    }

    private void ShowViewStateInfo()

    {

    StringBuilder sb = new StringBuilder();

    string info =string.Empty ;

    info = string.Format("Max:{0}", (int)this.ViewState["max"]);

    sb.Append(info);

    List<int> mylist = this.ViewState["list"] as List<int>;

    if(mylist!=null)

    {

    info = string.Format("List.Count:{0}", mylist.Count);

    sb.Append(System.Environment.NewLine);

    sb.Append(info);

    }

    Dictionary<string, int> myDic = this.ViewState["dic"] as Dictionary<string,int>;

    if(myDic !=null)

    {

    info = string.Format("Dictionary<string, int> :{0}",myDic.Count);

    sb.Append(System.Environment.NewLine);

    sb.Append(info);

    }

    Response.Write(sb.ToString());

    }

    经以上测试。单击button后ViewState存储List没有问题。

    5.4 StateBag TrackViewState 机制。(ViewState 是StateBag的实例)

    Post 时页面保存ViewState ,最终是否把ViewState中的值持久化到__ViewState中,这由 StateBag.IsItemDirty("key")决定。如果 StateBag.IsItemDirty("key")是true,标志数据被修改过,这时Control类会调用持久化方法,会把key对应的数据经过base64编码后写入__viewstate字段中。如果 StateBag.IsItemDirty("key")为false,Control就不会吧key对应的数据添加到__viewstate中。

    5.5 StateBag 简介

    注意:

    1) StateBag 只有在调用TrackViewState方法之后,修改它的键值,键对应的值才会被标记为Dirty。

    2)StateBag 只跟踪直接替换数据标记为Dirty,不跟踪引用修改数据。

    5.5. 1测试代码

    StateBag myBag=new StateBag();

    myBag["key"]=new List<int>();

    ((IStateManager)myBag).TrackViewState();

    List<int> mylist=myBag["key"] as List<int>;

    mylist.Add(1);

    Console.WriteLine(myBag.IsItemDirty("key"));    

    输出:False

    myBag["key"]=new List<int>(){1,2};

    Console.WriteLine(myBag.IsItemDirty("key"));

    输出:True

    (由于上述文档以前写在excel中,这次复制到writer中导致排版比较恶心,在此向大家致以歉意。文档中有不正确的地方欢迎大家指正。)

  • 相关阅读:
    javascript数据结构与算法---二叉树(查找最小值、最大值、给定值)
    javascript数据结构与算法---检索算法(二分查找法、计算重复次数)
    javascript数据结构与算法---检索算法(顺序查找、最大最小值、自组织查询)
    javascript数据结构与算法--高级排序算法(快速排序法,希尔排序法)
    ThinkPHP5中Session的使用
    能让你少写1000行代码的20个正则表达式
    composer 安装
    thinkphp5.0 实现图片验证效果且能点击图片刷新图片
    thinkphp5.0 实现单文件上传功能
    thinkphp5.0 输入变量
  • 原文地址:https://www.cnblogs.com/hbb0b0/p/1880531.html
Copyright © 2020-2023  润新知