比如向页面动态添加控件
为什么一定要先加入父控件的controls集合,才能保存初始状态不在回发的时候丢失?
比如:
CheckBoxList chk = new CheckBoxList();
form1.Controls.Add(chk); //A
if (!IsPostBack) //B
{
chk.Items.Add("Hello");
}
A放到B后面就出问题了,不理解?
树上说是调用了TrackViewState()方法
为什么一定要先加入父控件的controls集合,才能保存初始状态不在回发的时候丢失?
比如:
CheckBoxList chk = new CheckBoxList();
form1.Controls.Add(chk); //A
if (!IsPostBack) //B
{
chk.Items.Add("Hello");
}
A放到B后面就出问题了,不理解?
树上说是调用了TrackViewState()方法
解决方案 »
- ListInfo<Dictionary>的问题
- 分页的DAL中的一个简单问题
- 弹出的DIV显示在ActiveX控件前
- JavaScript: 如何让Vlidator在验证对象隐藏后失效?
- 点击删除按钮,如何弹出是否删除?
- 把一套 网站内容管理系统 如何放到群集服务器中
- 用delete删除记录,怎样让它不写入到db2日志文件中,谢谢
- 后台CS中如何将javascript中的方法所获得的值赋给TextBox?
- List<List<T>> 泛型怎么添加到集合
- 当listbox的selectionmode为multiple时,怎么得到所有以选定的项目那
- 机器安装的Visual Studio2005+SQL2005,现在想升级为Visual Studio2008+SQL2008,需要注意什么吗?
- 求JAVA书
http://www.cnblogs.com/jincwfly/archive/2007/03/19/680088.html
在Add方法中有启用控件视图状态的代码. 6.7 对动态添加控件的视图状态分析
这一节讲点与视图状态相关的有趣的东西。我们在开发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); } 以上代码首先动态创建一个ListBox控件lb,在页面第一次请求时(提交后不再执行此句)为它增加一个集合项“子项1”,最后把lb添加到当前form集合中。这时如果单击页面中事先放置的“提交”按钮,则页面提交后不再看到“子项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);} u 以上代码在为ListBox控件lb增加集合子项时之前,先启用Items属性的视图跟踪监控。这样当页面再提交时,则集合项“子项1”仍然能够呈现。扩展一下,多增加几个Item并设置几个为选中状态,再次提交页面,增加的几个item仍然能够被视图状态成功保存,且能够记住当前是否选中状态。这是为什么呢?原来ListBox控件的属性Items的继承基类ListControl中有个ListItemCollection类型的items对象,像“子项1”这些item就是被增加到items对象中进行管理的。关键的一点是,ListItemCollection集合对象实现了IStateManager接口,看一下它的类定义:/// <summary>/// 获得本书更多内容,请看:/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx/// </summary>public sealed class ListItemCollection : IList, ICollection, IEnumerable, IStateManager{ // Fields private ArrayList listItems; private bool ed; 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); void IStateManager.LoadViewState(object state); object IStateManager.SaveViewState(); 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; }} u ListItemCollection类实现了IStateManager接口下的几个视图状态相关方法,因为它自身具有视图状态管理能力。基于此,在增加到ListBox对象子项之前,调用这句:(lb.Items as IStateManager).TrackViewState();把它的视图跟踪监控功能打开,即从此刻起视图状态将记录它所有的修改,当然包括它增加的“子项1”项。这就是页面提交“子项1”仍然能够显示在页面上的原因。只有实现了IStateManger接口的集合才能够调用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"); }}
u 在上面的代码中对之前不能够保存视图状态的代码,仅调换了一下代码顺序。把this.form1.Controls.Add(lb)这句放到了lb.Item.Add(“子项1”)之前。运行页面并单击“提交”按钮,就会发现item“子项1”也能够保存视图状态。仅作了代码调整即使lb实现了视图状态保存,这是什么原因呢?这里的关键语句:this.form1.Controls.Add(lb);中的关键方法Add起了重要作用。Controls集合的Add方法最终调用的是Control控件基类中的方法AddedControl。直接看一下AddedControl的代码实现: /// <summary> /// 获得本书更多内容,请看: /// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx /// </summary> 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._occasionalFields != null) && (control._occasionalFields.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(); } } } } }
这是.NET类库代码,不必全部看懂。但要知道此方法能够启用视图状态和向页面请求注册控件状态(假如需要的话)。视图状态跟踪被启用后,接下来执行对item“子项1”的增加当然也能够被页框架视图管理器保存。这里有详细解释:【庖丁解牛:纵向切入Asp.net 3.5控件和组件开发技术系列—(6)页面状态机制(视图状态和控件状态)】
http://blog.csdn.net/ChengKing/archive/2009/01/01/3680485.aspx