asp.net 动态创建TextBox控件及状态数据如何加载

所属分类: 网络编程 / ASP.NET 阅读数: 1064
收藏 0 赞 0 分享

接着上文Asp.net TextBox的TextChanged事件你真的清楚吗? 这里我们来说说状态数据时如何加载的。
虽然在Control中有调用状态转存的方法,但是这里有一个判断条件 if (_controlState >= ControlState.ViewStateLoaded) 一般的get请求这里的条件是不满足的。

复制代码 代码如下:

internal enum ControlState
{
Constructed,
FrameworkInitialized,
ChildrenInitialized,
Initialized,
ViewStateLoaded,
Loaded,
PreRendered
}

我们知道在page的ProcessRequest中this.ControlState = ControlState.FrameworkInitialized;ProcessRequestMain方法中在Init后有调用this.InitRecursive(null);在这个方法里面有这么一句_controlState = ControlState.Initialized;,在LoadAllState()方法中有这么一句 base.LoadViewStateRecursive(second.Second);,而LoadViewStateRecursive中又有_controlState = ControlState.ViewStateLoaded这句带代码,所以我们在Page_load中动态条件控件时, if (_controlState >= ControlState.ViewStateLoaded)条件成立,如图:

所以在运行this.form1.Controls.Add(txt);这句以前,txt的值为demo1,

如图


但是运行以后之就发生变化了:

当然这里的txt.Text值也是我上次post过来的旧值,新值是在控件的LoadPostData方法中重新绑定。在默认的LoadViewStateRecursive方法中有一个很重要的判断

复制代码 代码如下:

internal void LoadViewStateRecursive(object savedState) {
// nothing to do if we have no state
if (savedState == null || flags[disableViewState])
return;

。。。。。。。

_controlState = ControlState.ViewStateLoaded
}

大家看到我上面是一个CustTextBoxt : TextBox控件,如果我们直接添加TextBox控件的话,那么着这里的txt.Text一直都是demo1,可见控件动态添加的时候是否加载状态数据与状态数据的保存有关。而状态数据的保存主要就是SaveViewState完成的,这里我第一次post的时候SaveViewState返回数据:

所以第二次能取到上次post过来的数据。

其中与SaveViewState有关的方法主要有:

复制代码 代码如下:

public class TextBox : WebControl, IPostBackDataHandler, IEditableTextControl {
protected override object SaveViewState() {
if (SaveTextViewState == false) {
ViewState.SetItemDirty("Text", false);
}
return base.SaveViewState();
}
private bool SaveTextViewState {
get {
//


// Must be saved when
// 1. There is a registered event handler for SelectedIndexChanged
// 2. Control is not enabled or visible, because the browser's post data will not include this control
// 3. The instance is a derived instance, which might be overriding the OnTextChanged method

if (TextMode == TextBoxMode.Password) {
return false;
}

if ((Events[EventTextChanged] != null) ||
(IsEnabled == false) ||
(Visible == false) ||
(ReadOnly) ||
(this.GetType() != typeof(TextBox))) {
return true;
}

return false;
}
}

}
public class WebControl : Control, IAttributeAccessor {
protected override object SaveViewState() {
Pair myState = null;

// Save values cached out of view state
if (_webControlFlags[disabledDirty]) {
ViewState["Enabled"] = !flags[isWebControlDisabled];
}

if (ControlStyleCreated) {
// the style shares the StateBag of its owner WebControl
// call SaveViewState to let style participate in state management
ControlStyle.SaveViewState();
}

object baseState = base.SaveViewState();
object aState = null;
if (attrState != null) {
aState = attrState.SaveViewState();
}

if (baseState != null || aState != null) {
myState = new Pair(baseState, aState);
}
return myState;
}
}
public class Control : IComponent, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor {
protected virtual object SaveViewState() {
// Save values cached out of view state
if (flags[visibleDirty]) {
ViewState["Visible"] = !flags[invisible];
}
if (flags[validateRequestModeDirty]) {
ViewState["ValidateRequestMode"] = (int)ValidateRequestMode;
}
if (_viewState != null)
return _viewState.SaveViewState();

return null;
}
}
public sealed class StateBag : IStateManager, IDictionary {
internal object SaveViewState() {
ArrayList data = null;
if (bag.Count != 0) {
IDictionaryEnumerator e = bag.GetEnumerator();
while (e.MoveNext()) {
StateItem item = (StateItem)(e.Value);
if (item.IsDirty) {
if (data == null) {
data = new ArrayList();
}
#if OBJECTSTATEFORMATTER
data.Add(new IndexedString((string)e.Key));
#else
data.Add(e.Key);
#endif
data.Add(item.Value);
}
}
}

return data;
}
}

到这里我们知道保存状态信息主要是在StateBag 的SaveViewState方法中,这里有一个检查  if (item.IsDirty) ,在TextBox的SaveViewState方法中有一个判断
复制代码 代码如下:

if (SaveTextViewState == false) {
ViewState.SetItemDirty("Text", false);
}

与它的SaveTextViewState 属性有关。

那么我们可以总结一下:动态创建的控件默认是在被添加的时候加载器状态数据,如果是静态添加的数据那就是LoadAllState来处理状态数据的加载。状态数据的加载与控件的SaveViewState密切相关,如果该方法的返回值为null既没有状态信息,那也不需要加载什么状态信息了。

更多精彩内容其他人还在看

.NET Core源码解析配置文件及依赖注入

这篇文章我们设计了一些复杂的概念,因为要对ASP.NET Core的启动及运行原理、配置文件的加载过程进行分析,依赖注入,控制反转等概念的讲解等
收藏 0 赞 0 分享

.NET Corek中Git的常用命令及实战演练

这篇文章将通过故事的形式从Git的历史谈起,并讲述Git的强大之处。然后通过实战演练教你如何在Github以及码云上托管我们的代码并进行代码的版本控制
收藏 0 赞 0 分享

Asp.Net Core WebAPI使用Swagger时API隐藏和分组详解

这篇文章主要给大家介绍了关于Asp.Net Core WebAPI使用Swagger时API隐藏和分组的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Asp.Net Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

如何利用FluentMigrator实现数据库迁移

这篇文章主要给大家介绍了关于如何利用FluentMigrator实现数据库迁移的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

ASP.NET Core利用Jaeger实现分布式追踪详解

这篇文章主要给大家介绍了关于ASP.NET Core利用Jaeger实现分布式追踪的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用ASP.NET Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

浅谈从ASP.NET Core2.2到3.0你可能会遇到这些问题

这篇文章主要介绍了ASP.NET Core2.2到3.0可能会遇到的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

详解.net core webapi 前后端开发分离后的配置和部署

这篇文章主要介绍了.net core webapi 前后端开发分离后的配置和部署,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁

这篇文章主要介绍了ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

.net 4.5部署到docker容器的完整步骤

这篇文章主要给大家介绍了关于.net 4.5部署到docker容器的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用.net4.5具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

.net core并发下线程安全问题详解

这篇文章主要给大家介绍了关于.net core并发下线程安全问题的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用.net core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享
查看更多