如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?

在Asp.Net页面的开发过程中,我们肯定经常会用到自定义的UserControl来复用部分页面元素,我们有两种使用UserControl的方式

1、在设计时往页面里添加需要的UserControl(最常用的就是从SolutionExplorer拖ascx到设计页面)

此种情况下,如果将UserControl放置在runat=server的html标签中,将可能导致UserControl内的元素事件处理不能正确执行。
例如:我们有时用一个div作为边框包含了需要的UserControl,而出于在运行时控制div的显示效果(比如运行时隐藏/显示这个div)的目的,可能将该div设为runat=server,此时,往往包含于div的UserControl内的元素事件触发可能被忽略,UserControl内的事件处理函数往往是不能正常运行的。

2、在运行时使用LoadControl函数动态载入UserControl,再Add到指定的位置

在动态载入的情况下,除了以上的问题同样存在之外,还会带来相应的初始化时的问题,这时,为了保证你的UserControl以你希望的语义正常运行,必须注意两点:

1)如果在LoadControl该UserControl的同时需要调用UserControl的某个初始化函数的话,该初始化函数的调用必须在将该ctlAdd到指定的页面某元素的Controls中之后进行,即必须按如下顺序:
...
MyCtl ctl = (MyCtl)LoadControl("path");
this.someCtl.Controls.Add(ctl);
ctl.InitMethod();//本语句必须在上一条之后,否则ctl中的事件导致PostBack后,需要保持的textbox、listbox等的数据将丢失,导致各种错误

2)如果在LoadControl该UserControl的同时需要调用UserControl的某个初始化函数的话,该函数体内要注意对不需每次执行的代码放入if (!IsPostBack){}语句块中,否则会导致每次提交时被重复运行,这和Page_Load中的处理方法其实是一样的,但往往容易被忽略。


对于动态载入的UserControl还要保证每次PostBack时都重新Load所有的UserControl(但PostBack时可以不初始化UserControl内的元素的初始值),否则事件处理函数会找不到对应的触发源,保存于ViewState的数据也将因找不到对应元素而保持不了。

posted on 2005-05-11 23:40 Teddy's Knowledge Base 阅读(6846) 评论(13) 编辑收藏 引用 收藏至365Key

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?

评论

 

好文章,谢谢!已收藏!回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-12 15:41 ASTAR Coming Now

======================
我们有时用一个div作为边框包含了需要的UserControl,而出于在运行时控制div的显示效果(比如运行时隐藏/显示这个div)的目的,可能将该div设为runat=server,此时,往往包含于div的UserControl内的元素事件触发可能被忽略,UserControl内的事件处理函数往往是不能正常运行的。
======================
webcontrols中的panel就是html的div服务器控件,而加入panel的usercontrol,不会出现事件被忽略的问题。
usercontrol的事件是否能被正确的触发,是取决于申明事件的位置是否正确。
通常都应该在pageload事件中申明。

=================================
MyCtl ctl = (MyCtl)LoadControl("path");
this.someCtl.Controls.Add(ctl);
ctl.InitMethod();//本语句必须在上一条之后,否则ctl中的事件导致PostBack后,需要保持的textbox、listbox等的数据将丢失,导致各种错误
=================================
把一个usercontrol加入到另外的contro控件里面,可以在
this.someCtl.Controls.Add(ctl); 之前调用该control的方法
也可以在之后调用此控件的方面,这没有什么分别。
有可能出错的是,该控件调用的方法有问题。

有问题,请给出代码大家研讨一下



回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-12 16:27 Teddy's Knowledge Base

首先我要说明,以上说到的情况都是小弟亲身经历过的,但不排除有其他原因导致的错觉,为了证实我的说法,在身边的电脑又做了个小测试,对于ASTAR Coming Now 不同意的情形一,没有重现出我说的错误,对于第二种情形,千真万确会出错!

请看示例程序:
http://teddy.51.net/test.rar

以上程序中WebForm1.aspx内包含三个WebUserControl1,
第一个是静态放置的,第二个第三个是动态Load的,只是第二个是以:
MyCtl ctl = (MyCtl)LoadControl("path");
ctl.InitMethod();
this.someCtl.Controls.Add(ctl);
顺序添加

第三个是以:
MyCtl ctl = (MyCtl)LoadControl("path");
this.someCtl.Controls.Add(ctl);
ctl.InitMethod();
顺序添加

请点击按钮,看执行效果!
回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-13 15:52 ASTAR Coming Now

我已经下载了你提供的代码,并作了相关实验了。
你发现的问题很好,这样讨论一下,有助于我们了解aspnet的模型。
这是你加载usercontrol的代码

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?privatevoidPage_Load(objectsender,System.EventArgse)
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
//在此处放置用户代码以初始化页面
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl11.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl1ctl
=(WebUserControl1)LoadControl("WebUserControl1.ascx");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
if(!IsPostBack)
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?ctl.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?this.Form1.Controls.Add(ctl);
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl1ctl2
=(WebUserControl1)LoadControl("WebUserControl1.ascx");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
this.Form1.Controls.Add(ctl2);
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
if(!IsPostBack)
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?ctl2.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

web程序运行后,你认为ctlpost事件有问题,即中间的那个usercontrol出现问题。
即:
post的时候无法触发事件。
安照你的代码,的确出现那样的问题。
不过我个人认为那是代码不合理造成的。
比如:
4/2=2这个是没有问题的,但是非要用4/0,肯定要出错。(可能说的有点严重,呵呵)
其实,上面的代码只注释一句就保证让那个usercontrol的事件在post的时候触发。
看代码
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?privatevoidPage_Load(objectsender,System.EventArgse)
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
//在此处放置用户代码以初始化页面
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl11.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl1ctl
=(WebUserControl1)LoadControl("WebUserControl1.ascx");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
//if(!IsPostBack) //就是这一句握!!
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?ctl.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?this.Form1.Controls.Add(ctl);
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl1ctl2
=(WebUserControl1)LoadControl("WebUserControl1.ascx");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
this.Form1.Controls.Add(ctl2);
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
if(!IsPostBack)
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?ctl2.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

究其原因是第一次加载页面的时候,运行了.InitCtl(),而postback的时候页面又没有运行了.InitCtl(),
当然就没有初始化下拉数据
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?publicvoidInitCtl()
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?TextBox1.Text
="initedbyInitCtl";
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?DropDownList1.Items.Add(
"item1");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?DropDownList1.Items.Add(
"item2");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?DropDownList1.Items.Add(
"item3");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

你会问我,为什么加载ctl2就不会出现这样的问题呢?
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?WebUserControl1ctl2=(WebUserControl1)LoadControl("WebUserControl1.ascx");
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
this.Form1.Controls.Add(ctl2);
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
if(!IsPostBack)
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
{
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?ctl2.InitCtl();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?}

也就是说为什么ctl2能够保持状态(所谓状态,指两样,值和事件),在第二次postback的时候能够触发事件呢?

因为ctl2也有子控件,它的子控件有
一个textbox,一个dropdownlist,一个button
而状态保存是靠什么保存的?viewstate,一个子控件如何从viewstate恢复?靠它自己的UniqueID从viewstate中恢复。
一个子控件还没有UniqueID就操作其控件这个本身就是不合理的。
所以,这也是ctl无法在post的触发事件,而ctl1确可以的真实原因

如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?myText=newTextBox();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
//myText.UniqueID为null
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?this.Controls.Clear();
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
this.Controls.Add(myText);
如何处理Asp.Net中页面运行时动态载入的UserControl内元素事件?
//此时myText.UniqueID不为null
见:
http://www.cnblogs.com/king_astar/archive/2004/09/30/48126.html

所以,
在this.someCtl.Controls.Add(ctl); 之前调用该control的方法或者在之后调用控件方法都可以,
不过不要加If(!ispostback)的判断,
如果一定要加postback的判断,则需要在子控件的UniqueID生成之后,再调用控件的方法。

 
回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-13 15:52 ASTAR Coming Now

mark回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-13 16:01 ASTAR Coming Now

修正一些东西,
实际上
ctl和ctrl1的button事件都是被触发的。
区别是
而只是里面的子控件,dropdownlist的子项没有保存或保存。回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-13 16:34 Teddy's Knowledge Base

确实很有可能是UniqueID的问题,曾经多次遇到此类问题是在我需要嵌套的动态Load页面控件时,嵌套控件内的元素的事件确实是可以触发并PostBack,但是,常常不能正确的定位到触发源,甚至,触发源被张冠李戴,不知是否也是因为UniqueID的问题,UniqueID应该是系统生成且只读的吧,这样的话理论上是不是不应该有重复的UniqueID发生呢?会不会有服务器端控件在最终执行时未被指定UniqueID的情况出现,从而导致被触发事件找不到触发源呢?有待进一步实验研究~~回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-06-11 16:07 s

博客堂上思归他们曾经讨论过这个问题。可以去参考一下。回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-08-11 20:44 天浩

我做了一个用户控件,控件里有个dropdownlist,我让它selectindexchanged时,就执行一段代码.但是这段代码执行了3次就不执行了.我查了好久,不知道原因,还望各位高手赐教啊!回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-08-11 20:58 Teddy's Knowledge Base

@天浩:

你这个情况如果是刚开始执行的,后来突然不执行了的话,一是检查一下dropdownlist.SelectedIndexChanged+=...这句是不是丢失了;
再有就是检查这个dropdownlist是不是处在另一个runat=server的控件内部,而两者的加载顺序相冲突。

当然以上只是猜测,要详细确定原因,还是必须针对具体的代码!回复

#re: Asp.Net中页面运行时动态载入的UserControl内元素的事件处理的注意事项 2005-05-12 09:09 jlzhou