|
正在开发一个Web控件, 但在集合数据保存(ViewState)这个问题上卡住了, 该控件主要是实现集合编辑器及动态增减命令按钮, 在设计时OK, 运行时也可以保存值的修改, 但是无法在运行时增加集合元素(回发后丢失, 集合元素还是在设计时指定的那些), 现附上部分说明问题的源代码文件, 请各位同仁指点迷津.(代码较多, 请见谅)
ItemBase 文件 -- 实现IStateManager的Item基类 /// <summary> /// 所有基于控件Item类的基类,实现IStateManger接口 /// IStateManager接口:定义任何类为支持服务器控件的视图状态管理而必须实现的属性和方法。 /// </summary> public class BaseItem: IStateManager { public BaseItem() { } private StateBag _ViewState = null; protected StateBag ViewState { get { if(_ViewState == null) { _ViewState = new StateBag(); if(((IStateManager)this).IsTrackingViewState) ((IStateManager)_ViewState).TrackViewState(); } return _ViewState; } } public void SetViewStateDirty() { if (_ViewState != null) { foreach (StateItem item in ViewState.Values) { item.IsDirty = true; } } } private bool _IsTrackingViewState = false; /// <summary> /// 获取控件是否在跟踪BaseItem实例的视图状态改变 /// </summary> bool IStateManager.IsTrackingViewState { get { return _IsTrackingViewState; } } void IStateManager.TrackViewState() { ((BaseItem)this).TrackViewState(); } protected virtual void TrackViewState() { _IsTrackingViewState = true; if(_ViewState != null) { ((IStateManager)_ViewState).TrackViewState(); } } object IStateManager.SaveViewState() { return ((BaseItem)this).SaveViewState(); } protected virtual object SaveViewState() { if(_ViewState != null) { return ((IStateManager)_ViewState).SaveViewState(); } return null; } void IStateManager.LoadViewState(object state) { ((BaseItem)this).LoadViewState(state); } protected virtual void LoadViewState(object state) { if(state != null) { ((IStateManager)ViewState).LoadViewState(state); } } }
ItemCollectionBase 文件 -- 实现集合编辑器及维护集合中ItemBase视图状态 [ Editor(typeof(ItemCollectionEditor), typeof(UITypeEditor)), ] public class BaseItemCollection: CollectionBase, IStateManager { public BaseItemCollection() { } private bool _IsTrackingViewState = false; bool IStateManager.IsTrackingViewState { get { return _IsTrackingViewState; } } public void SetViewStateDirty() { for(int i = 0; i < List.Count; i++) { ((BaseItem)List[i]).SetViewStateDirty(); } } /// <summary> /// 跟踪集合中所有元素的视图状态更改 /// </summary> void IStateManager.TrackViewState() { _IsTrackingViewState = true; foreach(BaseItem Item in List) { ((IStateManager)Item).TrackViewState(); } } /// <summary> /// 存储集合中所有元素的视图状态 /// </summary> /// <returns></returns> object IStateManager.SaveViewState() { object[] state = new object[2]; ArrayList Items; ArrayList Indices; if(List.Count > 0) { Items = new ArrayList(); Indices = new ArrayList(); for(int i = 0; i < List.Count; i++) { object Item = ((IStateManager)List[i]).SaveViewState(); if(Item != null) { Indices.Add(i); Items.Add(Item); } } if(Indices.Count > 0) { state[0] = Indices; state[1] = Items; } } return state; } void IStateManager.LoadViewState(object state) { if(state == null) return; object[] viewState = (object[])state; ArrayList Indices = viewState[0] as ArrayList; ArrayList Items = viewState[1] as ArrayList; if(Items != null) { for(int i = 0; i < Indices.Count; i++) { ((IStateManager)List[(int)Indices[i]]).LoadViewState(Items[i]); } } } }
继承自ItemBase和ItemCollectionBase的两个类 public class CommandButton: BaseItem { public CommandButton(CommandButtonCollection parent) { } public CommandButton(): this(null) { } } } public class CommandButtonCollection: BaseItemCollection { public CommandButtonCollection(): base() { } public void Add(CommandButton cmdButton) { List.Add(cmdButton); if(((IStateManager)this).IsTrackingViewState) { ((IStateManager)cmdButton).TrackViewState(); cmdButton.SetViewStateDirty(); //不注释这句, 会引发索引超出的异常, 应该是保存了新增元素的索引值, 但List的Count在下次回发后不变 } } public CommandButton this[int Index] { get { if(Index >= 0 && Index < base.List.Count) return (CommandButton)base.List[Index]; return null; } } }
下面是控件的部分关键代码:
[DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")] public class WebCustomControl1 : System.Web.UI.WebControls.WebControl { private CommandButtonCollection _CommandButtons; [ DefaultValue(null), PersistenceMode(PersistenceMode.InnerProperty), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), NotifyParentProperty(true), ] public CommandButtonCollection CommandButtons { get { if(_CommandButtons == null) { _CommandButtons = new CommandButtonCollection(); if(IsTrackingViewState) { ((IStateManager)_CommandButtons).TrackViewState(); } } return _CommandButtons; } }
protected override void Render(HtmlTextWriter output) { ... } protected override object SaveViewState() { object[] state = new object[] { base.SaveViewState(), ((IStateManager)CommandButtons).SaveViewState(), }; return state; } protected override void TrackViewState() { base.TrackViewState(); ((IStateManager)CommandButtons).TrackViewState(); } protected override void LoadViewState(object savedState) { if(savedState != null) { object[] state = (object[])savedState; base.LoadViewState(state[0]); ((IStateManager)CommandButtons).LoadViewState(state[1]); } } }
CommandButtons是一个集合, 维护所有CommandButton, 现在在运行时增加会有索引超出的异常(主要是在LoadViewState的时候, List上一次增加的元素丢失), 不知道问题出在哪了, 请各位同仁指教.
|