动态加载控件貌似给很多程序员都带来了困扰,经常收到这样的邮件,干脆就写下面这个示 例来演示如何解决那些常见的问题吧。
其实常见的问题通常有这样两个:
1. 通常他们都通过一个按钮来添加一个UserControl 并将它们加入PlaceHolder 容器的 Controls 中。然后页面上就会有一个另外一个按钮,这个按钮什么相关的事也没做,就是做了 一次回发。这样的情况动态添加的控件就不翼而飞了。
2. 今天收到了一封邮件说是要追加控件,和上面的情况看上去好像不一样,但实质就是同 一回事。
原因:
其实网上有很多帖子都不约而同地解释了这个问题,这里我还是不厌其烦地解释一下:
首先,要提到大家所熟知很多人一知半解的页面生命周期,以至于很多居然还停留在将 ASP.NET 和Winform 一样处理的层次上,因此就会有人试图将变量存在实例字段中,然后一如 既往地指望它能够用来共享数据,结果总是无功而返,以我所知这样的人居然还不在少数,当 然了,咱博客园的素质相对偏高,这种问题一般不在话下。事实上每次页面PostBack 都会从 Aspnet 线程池中返回一个空闲的用户线程,用于处理用户本次的请求。摆弄一下那种浏览器进 度条会动的控件基本也都算是回发事件了。两次回发之间可以当作没有什么关联的。但是你总 能看到很多控件等在回发之后还能保持状态比如文本框边上有个按钮。你填写完了文本后狂点 那个按钮,你会发现文本框中的文字还是你填写的那些而不会被清空。这就不得不说到 ViewState 这种神奇的双刃剑了。它的原理在MSDN 上讲的很清楚,找不到的留言或发邮件给我 我再慢慢给你找……
然后呢?还是查MSDN, 关键字“TemplateControl.LoadControl ” 我们在用PlaceHolder 中动态添加控件的时候就会用到这个方法了。我们注意到这里有一句:“ 在将控件加载到容器 控件时,该容器引发所添加控件的所有事件,直到所添加控件参与当前事件为止。但是,所添 加控件不参与回发数据处理。” 因为所添加的控件是不参与回发数据处理的,因此就会出现问 题1 中所遇到的按另一个按钮就消失的现象了。问题2 其实也是一样的问题,因为事实上它们 遇到的现象是一样的,只不过它的需求有所不同罢了。(可以理解成一个是i=1; 另一个是 i+=1; )
综上所述,问题的关键就是原本在页面加载的时候所有的控件初始化操作都应该完成,动态 加载将加载的过程延迟到了事件被触发之后,因此在页面回发后,因为会有一次新的页面加载 过程,显然这时候动态加载的控件是不存在的,但是用户预期的答案是显示已经加载的信息。 这时候如果可能我们最好在加载的过程中进行控件的重新加载和数据绑定。常见的方法中我们 呢通常通过LoadControl 来动态加载控件,因此只要在页面输出之前的所有事件节点上我们都 可以加载我们的控件。但是推荐的则是Init 事件。在Load 事件的时候进行数据绑定。