您的位置:首页 > 其它

对动态添加控件的视图状态分析

2011-04-30 20:53 399 查看
对动态添加控件的视图状态分析
我们在开发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();
}
}
}
}
}


我们知道此方法能够启用视图状态和向页面请求注册控件状态,看不懂也没关系。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐