作者:
王孟軍! 來源:
博客園 發布時間: 2008-09-25 15:25 閱讀: 5292 次 推薦: 0
原文鏈接 [收藏]
主題,控件的viewstate狀態
一“七七八八”
有次,朋友開玩笑說,不知道什么時候,微軟會取消viewstate,不再使用隱藏字段在服務器與客戶端保存狀態!雖然,可以使用客戶端技術減少一些回傳,但是,一些必要的服務器狀態還是要保存的,現在網絡帶寬已經不是問題,所以在網絡上適當的傳遞一些狀態數據,還是可以容忍的!當然,如果終端是mobile,可以考慮把viewstate保存到服務器上!
二“誤解viewstate”
園子里,有不少描寫viewstate的文字,也看了不少,知道Viewstate實現了IStateManager接口的一個屬性和三個方法!剛接觸“她”的時候,一直以為control對象直接實現了IStateManager接口,模糊的記得好象有幾個LoadViewstate和SaveViewstate方法,也沒有在意方法有沒有override修飾!后來發現不是這樣的,control并沒有直接實現IStateManager接口,而是通過定義一個StateBar類型的Viewstate屬性,委托Viewstate屬性去管理狀態,也就是讓StateBar類型去真正實現狀態的管理,這種方式可以使控件本身和viewState的實現完全分離!也許,這些經驗,對高手談不上是“經驗”,希望剛入門的同仁能少走點彎路!
三“結合Style樣式,淺談Viewstate”
Viewstate屬性能裝載的數據類型比較有限,但是有些不能加載的類型怎么辦呢?當然是重寫
IStateManager了,然后WebControl委托給ControlStyle屬性來管理狀態,有點象WebControl
定義ViewState屬性
還是從簡單的入手吧,直接使用Style類型的狀態管理
目標,定義一個文本框和一個按鈕的復合控件
要點,分別給文本框和按鈕各自定義樣式,并提升她們為頂級樣式屬性
圖一
圖二 (文本框和按鈕的樣式)
圖四 Demo

Code
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.ComponentModel.Design;

namespace WebControlLibrary


{
[
DefaultEvent("Button"),
DefaultProperty("Text"),
//Designer(typeof(WebControlLibrary.Design.CustomerControlDesigner))
]
public class WebCustomControl1 : CompositeControl

{
//聲明變量
private Button _button;
private TextBox _textBox;
private static readonly object EventButtonClick = new object();
private Style _buttonStyle;
private Style _textBoxStyle;

//定義屬性Text,用于指定按鈕上的文字
[
Bindable(true),
Category("Appearance"),
DefaultValue(""),
Description("獲取或設置顯示顯示在按鈕上的文字")
]
public string Text

{
get

{
EnsureChildControls();
return _button.Text;
}

set

{
EnsureChildControls();
_button.Text = value;
}
}

//定義ButtonStyle屬性
[
Category("Style"),
Description("設置Button的樣式屬性"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty),
]
public virtual Style ButtonStyle

{
get

{
if (_buttonStyle == null)

{
_buttonStyle = new Style();
if (IsTrackingViewState)

{
((IStateManager)_buttonStyle).TrackViewState();
}
}
return _buttonStyle;
}
}

//定義TextStyle屬性
[
Category("Style"),
Description("設置TextBox的樣式屬性"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
NotifyParentProperty(true),
PersistenceMode(PersistenceMode.InnerProperty),
]
public virtual Style TextBoxStyle

{
get

{
if (_textBoxStyle == null)

{
_textBoxStyle = new Style();
if (IsTrackingViewState)

{
((IStateManager)_textBoxStyle).TrackViewState();
}
}
return _textBoxStyle;
}
}

//重寫Controls屬性
public override ControlCollection Controls

{
get

{
EnsureChildControls();
return base.Controls;
}
}

//重寫CreateChildControls方法,將子控件添加到復合控件中
protected override void CreateChildControls()

{
Controls.Clear();
_button = new Button();
_textBox = new TextBox();
_button.ID = "btn";
_button.CommandName = "ButtonClick";
this.Controls.Add(_button);
this.Controls.Add(_textBox);
}

//重寫Render方法,呈現控件中其他的HTML代碼
protected override void Render(HtmlTextWriter output)

{
//AddAttributesToRender(output);
if (_textBoxStyle != null)

{
_textBox.ApplyStyle(TextBoxStyle);
}
if (_buttonStyle != null)

{
_button.ApplyStyle(ButtonStyle);
}
output.AddAttribute(HtmlTextWriterAttribute.Border, "0px");
output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "5px");
output.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "0px");
output.RenderBeginTag(HtmlTextWriterTag.Table);
output.RenderBeginTag(HtmlTextWriterTag.Tr);
output.RenderBeginTag(HtmlTextWriterTag.Td);
_textBox.RenderControl(output);
output.RenderEndTag();
output.RenderBeginTag(HtmlTextWriterTag.Td);
_button.RenderControl(output);
output.RenderEndTag();
output.RenderEndTag();
output.RenderEndTag();
}

//事件處理
public event EventHandler ButtonClick

{
add

{
Events.AddHandler(EventButtonClick, value);
}
remove

{
Events.RemoveHandler(EventButtonClick, value);
}
}

protected virtual void OnButtonClick(EventArgs e)

{
EventHandler buttonClickHandler = (EventHandler)Events[EventButtonClick];
if (buttonClickHandler != null)

{
buttonClickHandler(this, e);
}
}

protected override bool OnBubbleEvent(object sender, EventArgs e)

{
bool handled = false;
if (e is CommandEventArgs)

{
CommandEventArgs ce = (CommandEventArgs)e;
if (ce.CommandName == "ButtonClick")

{
OnButtonClick(EventArgs.Empty);
handled = true;
}
}
return handled;
}

//樣式狀態管理,重寫3個相關方法
protected override void LoadViewState(object savedState)

{
if (savedState == null)

{
base.LoadViewState(null);
return;
}
if (savedState != null)

{
object[] myState = (object[])savedState;
if (myState.Length != 3)

{
throw new ArgumentException("無效的ViewState");
}
base.LoadViewState(myState[0]);
if (myState[1] != null)

{
((IStateManager)TextBoxStyle).LoadViewState(myState[1]);
}
if (myState[2] != null)

{
((IStateManager)ButtonStyle).LoadViewState(myState[2]);
}
}
}

protected override object SaveViewState()

{
object[] myState = new object[3];
myState[0] = base.SaveViewState();
myState[1] = (_textBoxStyle != null) ? ((IStateManager)_textBoxStyle).SaveViewState() : null;
myState[2] = (_buttonStyle != null) ? ((IStateManager)_buttonStyle).SaveViewState() : null;

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

{
if (myState[i] != null)

{
return myState;
}
}
return null;
}

protected override void TrackViewState()

{
base.TrackViewState();

if (_buttonStyle != null)

{
((IStateManager)_buttonStyle).TrackViewState();
}
if (_textBoxStyle != null)

{
((IStateManager)_textBoxStyle).TrackViewState();
}
}
}
}

Demo比較簡單,在類頂部定義了兩個Style類型的屬性,然后重寫維護狀態的三個方法一個屬性
注意
1.這里并不是直接重寫IStateManager接口
2.重寫 SaveViewState 方法以將附加樣式屬性保存到 ViewState
3.重寫 LoadViewState 方法以自定義從 ViewState 的附加樣式屬性的還原
4.必須以添加它們的相同順序檢索
四 控件狀態的細節遠不只是這些,有不妥當的地方,還望同仁指出...(后續)
文章列表