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

1 自定义控件之状态管理     

 

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

 

1 自定义控件之状态管理    

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

名称 说明
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后控件的状态仍然保留。效果如下图所示。

   1 自定义控件之状态管理

 

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 时生成工作正常

   1 自定义控件之状态管理

 

4.2.2 在post 时丢失状态

1 自定义控件之状态管理

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

 

BarGraphControlWithViewStateProperty post时的__ViewState

1 自定义控件之状态管理

 

BarGraphControl post 时的回传数据

1 自定义控件之状态管理

 

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

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

          5.1.1BarGraphControl get时页面生成的__ViewState

    <input type="hidden" name="__VIEWSTATE" ));

输出:True

 

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

相关文章: