我有一个ASP.NET Web表单复合控件,让我们称之为控件A,它包含一个子复合控件,我将其称为控件B.控件B的子控件依赖于控件A的属性。
在初始加载时,我在控件A的OnLoad中设置此参数,一切正常,控件B在CreateChildControls中正确设置其子控件。
但是,当我想在控件A的下拉列表中通过SelectedIndexChanged更改此参数时,事件处理程序似乎在生命周期中处理得太迟,以便控件B获取更改的值。大概这是因为已经调用了控件B的CreateChildControls方法。
如何让控件B以这样的方式更新其子控件,以便它们可以经历正常的生命周期,根据需要加载viewstate?
为了清楚起见,当控件A的参数被更改时,控件B的子控件可能必须保留一些,一些需要删除,一些需要添加,因此保留它们的那些仍然需要加载状态。
答案 0 :(得分:4)
SelectedIndexChanged事件将在页面的Page_Load(OnLoad)和控件A之后处理。您正确认为您的页面已经重建,并且当您到达此事件处理程序时,viewstate会恢复为控件 - 应该是,当页面/控件尚未重建时,处理事件的重点是什么?
我建议的三个简单的解决方案是:
没有控件B检查其父级的值,然后相应地构建自己,这是一个反模式。相反,让控件A加载正确版本的控件B,具体取决于下拉列表的值。 IOW让控制A负责加载的内容,而不是控制B.控制B应该是愚蠢的,不关心它的父级是什么。如果需要与其父接口进行接口,则应通过接口进行接口。
如果您只是隐藏和显示字段,那么只需将它们全部放在控件B中,并隐藏那些不应显示的字段。如果将visible属性设置为false,大多数控件都不会将任何HTML呈现给输出流,因此当页面被发送回客户端时对客户端的影响最小
具有控制权A根据所选值重建部分。它可以包含一个DIV,你做一个div.Controls.Clear(),然后将正确的控件添加回来。在SelectedIndexChanged事件中可以这样做,因为你不关心那些控件已经存在以及它们的值是什么(如果你关心一些现有的控件,那么不清楚那些来自那里的那些是相对微不足道的。控制集合并在它们周围添加新控件)
这三种方法中的每一种都有它的优点和缺点,你可能最终做的是这三种方法的混合。还有另一种可能的方法,您可以使用PageParser及其GetCompiledPageInstance方法来获取用于重新生成页面的IHttpHandler,但这是通过此处的小回复覆盖的高级方法。