动态加载控件UserControl到页面上:视图状态问题
2007-11-08 15:41
387 查看
前言:一些介绍[/b]
动态加载控件
视图状态的保存
重构页面/控件
初始化页面/控件/IsPostBack
了解一下控件的生命周期。
1:Instantiate
2:Initialize
3:Begin Tracking View State
4:Load View State (postback only)
5:Load Postback Data (postback only)
6:Load
7:Raise Changed Events (postback only, optional)
8:Raise Postback Events (postback only, optional)
9:PreRender
10:SaveViewState
11:Render
12:Unload
13:Dispose
视图状态[/b]:ViewState,asp.net提供的一个集合,用来保存页面上控件的状态。
视图状态的恢复[/b]:asp.net会在某个特定的时刻(Load View State)把保留在ViewState集合中的数据恢复到相应的控件中(根据该控件的id)
控件状态的追赶论[/b]:在contrlParant(已经到状态n,n肯定就在上述13个中的一个)中加入一个contrlChild,那么controlChild的状态在controlParent.Control.Add(contrlChild)之后就会立即经历n-1个状态,到达和contrlParant同步的状态。
-------------------------
这是一个困扰了我近两年的问题。刚开始是无法恢复状态;后来想办法恢复了状态但是无法避免重复的初始化(浪费效率);再后来解决了,但是认识比较浅。今天终于有所悟。
问题的提出:[/b]在一个aspx页面上,根据传递的参数来加载不同的UserControl。保证UserControl的顺利执行还有效率:
今天在网上搜索,得到这样的文章http://www.cnblogs.com/alex.zhang/archive/2005/03/31/129427.html。里面写得洋洋洒洒。结合我自己的应用,简单的说一下。
问题在哪里?
比如你在一个Page_Load事件里面这样写
protected void Page_Load(object sender, EventArgs e)
void btn_Click(object sender, EventArgs e)
那么,你下次回发这个页面之后(点击按钮之后),这个按钮就消失了。因为没有重构(控件只是生成了一次,因为在if (!IsPostBack)里面)。
这部分,需要了解不少关于ViewState和asp.net的生命周期的知识。简单的说,asp.net根据页面上的控件树来恢复状态,但是由于控件是在程序中生成,并且只生成了一次,所以在叶面提交的时候asp.net没有找到该控件的id,自然也不会重构他,页面上也就显示不出来这个控减了。
如果这样就可以重构:去掉if (!IsPostBack),每次都加载
protected void Page_Load(object sender, EventArgs e)
但是问题依然有,它的事件你可能捕捉不到(这个例子太简单,如果控件数量多,他们的id的生成就会很意外,导致找不到一样的id)。对象的状态的恢复是根据控件的id来进行的。如果id不确定(自动生成的id),那么它也就无法恢复状态。启动叶面的trace 可以看到这棵控件树。大体这样:
如果一下子生成大量控件的时候,由于id的不确定,两次生成的控件id可能不一样,所以也无法正确恢复状态。
所以我们需要确定的id。比如这样:
Button btn = new Button();
btn.Click += new EventHandler(btn_Click);
btn.Text = "Click Me";
btn.ID ="btn_t";
this.PlaceHolder1.Controls.Add(btn);
这样呢?看上去可以了。但是问题是,你做了重复的初始化工作(每次Page_Load都在初始化这个控件)。如果我们把应用放到UserControl上,我们动态加载的是一个UserControl,而这个Control的初始化事件又非常耗时
比如:
public partial class Agent_uc1 : System.Web.UI.UserControl
那么,这个实现就太没效率了,付出了高昂的代价。
怎么解决呢?
先看我引用的文章的一点描述,然后再说我的实现[/b]
道行限制,也没仔细看,所以不敢说看懂了多少。
文章主要使用那个“控件状态追赶论”来解释的。先加入控件(主要是id配对),然后就可以被正确加载(追赶过程中有一步会根据控件id来恢复视图状态)。
我的实现就是这样的:[/b]
//Page的基类
public class BasePattern:Page
public class BaseView:UserControl
protected void lbt_summary_Click(object sender, EventArgs e)
1:必须每次都执行创建该控件的工作。其实主要是建立这个控件的名称,恢复控件树
protected override void OnInit(EventArgs e)
这个事件比Page_Load靠前。
2:保证id一样
ctl.ID = path;//让同一个控件的id唯一。
3:区分重建和执行
所以在Page德类里面我用的是两个函数Rebuild()和LoadModule(),目的就是区分这两个调用。内部的重建只是使用Rebuild,只是建立一个控件id的过程,外部调用的时候,就需要调用控件的初始化函数了
结论就是[/b]:
1:在特定的时刻加入该控件的定义。至少在Page_Load以前,我用的Page_Init。晚了就执行不了了
2:该控件的id必须一致。因为状态的恢复是根据控件id来完成的。
3:Rebuild的时候一定不要调用子控件的初始化的函数,这样会浪费时间。
问题[/b]:可不可以通过设置UserControl的IsPostBack属性来达到一种和Page类似的处理方式呢?这样在UserControl里面就可以使用if(!IsPostBack)来做一些数据初始化了。
我记得我曾经看过一篇文章,可以在某个事件中设置IsPostBack属性,但是现在怎么也找不到这篇文章了,可惜得很。
动态加载控件
视图状态的保存
重构页面/控件
初始化页面/控件/IsPostBack
了解一下控件的生命周期。
1:Instantiate
2:Initialize
3:Begin Tracking View State
4:Load View State (postback only)
5:Load Postback Data (postback only)
6:Load
7:Raise Changed Events (postback only, optional)
8:Raise Postback Events (postback only, optional)
9:PreRender
10:SaveViewState
11:Render
12:Unload
13:Dispose
视图状态[/b]:ViewState,asp.net提供的一个集合,用来保存页面上控件的状态。
视图状态的恢复[/b]:asp.net会在某个特定的时刻(Load View State)把保留在ViewState集合中的数据恢复到相应的控件中(根据该控件的id)
控件状态的追赶论[/b]:在contrlParant(已经到状态n,n肯定就在上述13个中的一个)中加入一个contrlChild,那么controlChild的状态在controlParent.Control.Add(contrlChild)之后就会立即经历n-1个状态,到达和contrlParant同步的状态。
-------------------------
这是一个困扰了我近两年的问题。刚开始是无法恢复状态;后来想办法恢复了状态但是无法避免重复的初始化(浪费效率);再后来解决了,但是认识比较浅。今天终于有所悟。
问题的提出:[/b]在一个aspx页面上,根据传递的参数来加载不同的UserControl。保证UserControl的顺利执行还有效率:
今天在网上搜索,得到这样的文章http://www.cnblogs.com/alex.zhang/archive/2005/03/31/129427.html。里面写得洋洋洒洒。结合我自己的应用,简单的说一下。
问题在哪里?
比如你在一个Page_Load事件里面这样写
protected void Page_Load(object sender, EventArgs e)
void btn_Click(object sender, EventArgs e)
那么,你下次回发这个页面之后(点击按钮之后),这个按钮就消失了。因为没有重构(控件只是生成了一次,因为在if (!IsPostBack)里面)。
这部分,需要了解不少关于ViewState和asp.net的生命周期的知识。简单的说,asp.net根据页面上的控件树来恢复状态,但是由于控件是在程序中生成,并且只生成了一次,所以在叶面提交的时候asp.net没有找到该控件的id,自然也不会重构他,页面上也就显示不出来这个控减了。
如果这样就可以重构:去掉if (!IsPostBack),每次都加载
protected void Page_Load(object sender, EventArgs e)
但是问题依然有,它的事件你可能捕捉不到(这个例子太简单,如果控件数量多,他们的id的生成就会很意外,导致找不到一样的id)。对象的状态的恢复是根据控件的id来进行的。如果id不确定(自动生成的id),那么它也就无法恢复状态。启动叶面的trace 可以看到这棵控件树。大体这样:
__Page | ASP.agent_default_aspx | 2411 | 0 | 0 |
ctl02 | System.Web.UI.LiteralControl | 148 | 0 | 0 |
ctl00 | System.Web.UI.HtmlControls.HtmlHead | 46 | 0 | 0 |
ctl01 | System.Web.UI.HtmlControls.HtmlTitle | 33 | 0 | 0 |
ctl03 | System.Web.UI.LiteralControl | 14 | 0 | 0 |
form1 | System.Web.UI.HtmlControls.HtmlForm | 2183 | 0 | 0 |
ctl04 | System.Web.UI.LiteralControl | 10 | 0 | 0 |
ScriptManager1 | Microsoft.Web.UI.ScriptManager | 224 | 0 | 0 |
ctl05 | System.Web.UI.LiteralControl | 29 | 0 | 0 |
PlaceHolder1 | System.Web.UI.WebControls.PlaceHolder | 64 | 0 | 0 |
btn_t | System.Web.UI.WebControls.Button | 64 | 0 | 0 |
ctl06 | System.Web.UI.LiteralControl | 14 | 0 | 0 |
Button1 | System.Web.UI.WebControls.Button | 76 | 0 | 0 |
ctl07 | System.Web.UI.LiteralControl | 22 | 0 | 0 |
ctl08 | System.Web.UI.LiteralControl | 20 | 0 | 0 |
所以我们需要确定的id。比如这样:
Button btn = new Button();
btn.Click += new EventHandler(btn_Click);
btn.Text = "Click Me";
btn.ID ="btn_t";
this.PlaceHolder1.Controls.Add(btn);
这样呢?看上去可以了。但是问题是,你做了重复的初始化工作(每次Page_Load都在初始化这个控件)。如果我们把应用放到UserControl上,我们动态加载的是一个UserControl,而这个Control的初始化事件又非常耗时
比如:
public partial class Agent_uc1 : System.Web.UI.UserControl
那么,这个实现就太没效率了,付出了高昂的代价。
怎么解决呢?
先看我引用的文章的一点描述,然后再说我的实现[/b]
道行限制,也没仔细看,所以不敢说看懂了多少。
文章主要使用那个“控件状态追赶论”来解释的。先加入控件(主要是id配对),然后就可以被正确加载(追赶过程中有一步会根据控件id来恢复视图状态)。
我的实现就是这样的:[/b]
//Page的基类
public class BasePattern:Page
public class BaseView:UserControl
protected void lbt_summary_Click(object sender, EventArgs e)
1:必须每次都执行创建该控件的工作。其实主要是建立这个控件的名称,恢复控件树
protected override void OnInit(EventArgs e)
这个事件比Page_Load靠前。
2:保证id一样
ctl.ID = path;//让同一个控件的id唯一。
3:区分重建和执行
所以在Page德类里面我用的是两个函数Rebuild()和LoadModule(),目的就是区分这两个调用。内部的重建只是使用Rebuild,只是建立一个控件id的过程,外部调用的时候,就需要调用控件的初始化函数了
结论就是[/b]:
1:在特定的时刻加入该控件的定义。至少在Page_Load以前,我用的Page_Init。晚了就执行不了了
2:该控件的id必须一致。因为状态的恢复是根据控件id来完成的。
3:Rebuild的时候一定不要调用子控件的初始化的函数,这样会浪费时间。
问题[/b]:可不可以通过设置UserControl的IsPostBack属性来达到一种和Page类似的处理方式呢?这样在UserControl里面就可以使用if(!IsPostBack)来做一些数据初始化了。
我记得我曾经看过一篇文章,可以在某个事件中设置IsPostBack属性,但是现在怎么也找不到这篇文章了,可惜得很。
相关文章推荐
- 动态加载控件UserControl到页面上 . 视图状态问题
- 关于Asp.net 页面动态加载用户控件,出现“未能加载视图状态”的原因[续]
- 关于Asp.net 页面动态加载用户控件,出现“未能加载视图状态”的原因
- 关于Asp.net 页面动态加载用户控件,出现“未能加载视图状态”的原因
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- 关于视图状态(ViewState)/动态控件的问题
- 未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配
- 未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配。
- .net 错误:动态加载控件时出现错误:未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。
- ASP.Net 动态加载控件 未能加载视图状态 的解决
- web页面动态加载UserControl,并调用用户控件中的方法来初始化控件
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- 关于页面动态加载控件当页面回发后控件消失的问题
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- jQuery EasyUI动态添加控件或者ajax加载页面后不能自动渲染问题的解决方法
- Asp.net开发心得点滴[动态加载的用户控件使用事件委托,交给页面处理的事件无效问题]
- ASP.NET Post页面及验证视图状态MAC失败问题的正确解决办法