对动态添加控件的视图状态分析
2011-04-30 20:53
399 查看
对动态添加控件的视图状态分析
我们在开发asp.net页面时,有时候在Page_Load事件中动态创建控件,而当页面提交后,动
态修改的数据就丢失了。
举个例子,看看如下代码:
如果单击页面事先放置的“提交”按钮,则页面提交后不再看到"子项1",也就是说在视图
状态中没有存储该item项。
为解决此问题,我们把代码修改为:
在这里启用了items属性的视图跟踪监控。因为ListBox控件属性Items的继承基类ListControl中有个ListItemCollection类型的items对象,ListItemCollection集合对象实现了IStateManager接口。看看他的类定义:
只有实现IStateManager接口的集合才能够调用TrackViewState方法打开视图监控。如果没有实现该接口对象,还有一种方法可以实现视图状态功能,把代码改为:
其中关键方法Add起了重要作用。Controls集合的Add方法最终调用的是Control控件基类的AddedControl方法,让我们来看看它的定义
我们知道此方法能够启用视图状态和向页面请求注册控件状态,看不懂也没关系。
我们在开发asp.net页面时,有时候在Page_Load事件中动态创建控件,而当页面提交后,动
态修改的数据就丢失了。
举个例子,看看如下代码:
protected void Page_Load(object sender, EventArgs e) { ListBox lb = new ListBox(); if (!Page.IsPostBack) { lb.Items.Add("子项1"); } this.form1.Controls.Add(lb); }
如果单击页面事先放置的“提交”按钮,则页面提交后不再看到"子项1",也就是说在视图
状态中没有存储该item项。
为解决此问题,我们把代码修改为:
protected void Page_Load(object sender, EventArgs e) { ListBox lb = new ListBox(); (lb.Items as IStateManager).TrackViewState(); if (!Page.IsPostBack) { lb.Items.Add("子项1"); } this.form1.Controls.Add(lb); }
在这里启用了items属性的视图跟踪监控。因为ListBox控件属性Items的继承基类ListControl中有个ListItemCollection类型的items对象,ListItemCollection集合对象实现了IStateManager接口。看看他的类定义:
public sealed class ListItemCollection : IList, ICollection, IEnumerable, IStateManager { // Fields private ArrayList listItems; private bool marked; private bool saveAll; // Methods public ListItemCollection(); public void Add(string item); public void Add(ListItem item); public void AddRange(ListItem[] items); public void Clear(); public bool Contains(ListItem item); public void CopyTo(Array array, int index); public ListItem FindByText(string text); internal int FindByTextInternal(string text, bool includeDisabled); public ListItem FindByValue(string value); internal int FindByValueInternal(string value, bool includeDisabled); public IEnumerator GetEnumerator(); public int IndexOf(ListItem item); public void Insert(int index, string item); public void Insert(int index, ListItem item); internal void LoadViewState(object state); public void Remove(string item); public void Remove(ListItem item); public void RemoveAt(int index); internal object SaveViewState(); int IList.Add(object item); bool IList.Contains(object item); int IList.IndexOf(object item); void IList.Insert(int index, object item); void IList.Remove(object item); [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] void IStateManager.LoadViewState(object state); [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] object IStateManager.SaveViewState(); [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] void IStateManager.TrackViewState(); internal void TrackViewState(); // Properties public int Capacity { get; set; } public int Count { get; } public bool IsReadOnly { get; } public bool IsSynchronized { get; } public ListItem this[int index] { get; } public object SyncRoot { get; } bool IList.IsFixedSize { get; } object IList.this[int index] { get; set; } bool IStateManager.IsTrackingViewState { get; } }
只有实现IStateManager接口的集合才能够调用TrackViewState方法打开视图监控。如果没有实现该接口对象,还有一种方法可以实现视图状态功能,把代码改为:
protected void Page_Load(object sender, EventArgs e) { ListBox lb = new ListBox(); this.form1.Controls.Add(lb); if (!Page.IsPostBack) { lb.Items.Add("子项1"); } }
其中关键方法Add起了重要作用。Controls集合的Add方法最终调用的是Control控件基类的AddedControl方法,让我们来看看它的定义
protected internal virtual void AddedControl(Control control, int index) { if (control.OwnerControl != null) { throw new InvalidOperationException(SR.GetString("Substitution_NotAllowed")); } if (control._parent != null) { control._parent.Controls.Remove(control); } control._parent = this; control._page = this.Page; control.flags.Clear(0x20000); Control namingContainer = this.flags[0x80] ? this : this._namingContainer; if (namingContainer != null) { control.UpdateNamingContainer(namingContainer); if ((control._id == null) && !control.flags[0x40]) { control.GenerateAutomaticID(); } else if ((control._id != null) || (control._controls != null)) { namingContainer.DirtyNameTable(); } } if (this._controlState >= ControlState.ChildrenInitialized) { control.InitRecursive(namingContainer); if (((control._controlState >= ControlState.Initialized) && (control.RareFields != null)) && control.RareFields.RequiredControlState) { this.Page.RegisterRequiresControlState(control); } if (this._controlState >= ControlState.ViewStateLoaded) { object savedState = null; if ((this._occasionalFields != null) && (this._occasionalFields.ControlsViewState != null)) { savedState = this._occasionalFields.ControlsViewState[index]; if (this.LoadViewStateByID) { control.EnsureID(); savedState = this._occasionalFields.ControlsViewState[control.ID]; this._occasionalFields.ControlsViewState.Remove(control.ID); } else { savedState = this._occasionalFields.ControlsViewState[index]; this._occasionalFields.ControlsViewState.Remove(index); } } control.LoadViewStateRecursive(savedState); if (this._controlState >= ControlState.Loaded) { control.LoadRecursive(); if (this._controlState >= ControlState.PreRendered) { control.PreRenderRecursiveInternal(); } } } } }
我们知道此方法能够启用视图状态和向页面请求注册控件状态,看不懂也没关系。
相关文章推荐
- 未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配。
- 未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配
- 关于Asp.net 页面动态加载用户控件,出现“未能加载视图状态”的原因
- 思归的“动态控件的状态问题”的分析
- 动态加载控件UserControl到页面上:视图状态问题
- 动态创建ASP.NET控件并保持其状态分析及实现
- android 获取控件屏幕位置 动态添加 视图
- 动态创建的控件不能保存视图状态
- 关于Asp.net 页面动态加载用户控件,出现“未能加载视图状态”的原因
- ASP.Net 动态加载控件 未能加载视图状态 的解决
- 关于视图状态(ViewState)/动态控件的问题
- android一个动态添加删除网格视图的demo,可把状态保存在数据库中
- .net 错误:动态加载控件时出现错误:未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。
- 思归的“动态控件的状态问题”的分析
- UIKit---UIButton状态,平移,缩放,代码方式动态添加控件
- 动态加载控件UserControl到页面上 . 视图状态问题
- 动态控件的状态问题的分析 概括
- [原]控件视图状态分析之 - 用户控件静态加载
- 思归的“动态控件的状态问题”的分析中用WinDbg跟踪TrackViewState方法的步骤
- 关于Asp.net 页面动态加载用户控件,出现“未能加载视图状态”的原因[续]