动态加载的控件:轻松实现
非臃肿的方式重新加载动态加载的控件,并保持事件处理完好。
引言
当使用动态加载的控件(通过使用.loadcontrol()
方法)时,需要考虑多个方面,特别是需要解决以下三个问题。
- 控件在回发后不能消失(第一个问题)
- 控件的内容必须被保留(第二个问题)
- 控件内的事件必须仍然触发(第三个问题)
此处最重要的是第 3 点。 例如,如果在Page_Load
事件期间重新加载控件,则控件内的事件将不会触发。(如果在Page_Init
期间重新加载它们,则很难跟踪必须加载的内容,正如您最初可能认为的那样。)
这是一种实现此目的的直接方法。
背景
动态加载的控件通过如下代码加载到代码隐藏文件中
Sub myButton_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles myButton.Click
tempcontrol = LoadControl("mycontrol.ascx")
tempcontrol.ID = tmpName
pContainer.Controls.Add(tempcontrol)
End Sub
如果您是完全的新手,您可以并行阅读另一篇文章。
解决第一个问题
控件可能如下所示
<%@ Control Language="VB" Inherits="mycontrol" %>
<asp:textbox id="myText" runat="server" ></asp:textbox>
单击mybutton
后,mycontrol
将出现在页面上,因为单击事件添加了它。 但是在下一次回发时,它会消失,因为没有人添加它。 所以让我们添加它
Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles mybase.Init
if Do_I_have_to_Load(tmpName) then
tempcontrol = LoadControl("mycontrol.ascx")
tempcontrol.ID = tmpName
pContainer.Controls.Add(tempcontrol)
End if
End Sub
稍后我将解释如何获取Do_I_have_to_Load
和tmpName
。
解决第二个问题
这一个是简短的:上面代码中有一行
tempcontrol.ID = tmpName
您所要做的就是始终为相同的控件提供相同的 ID。 然后Viewstate
和Postback
数据将被保留。(这很容易,并且在许多其他文章中都有提到。)
解决第三个问题
这是本文的核心,尽管它已经在上面的代码中解决了,当我提到使用 INIT 事件重新加载控件时,这将连接用户控件内的所有事件。(我指的是未动态添加的事件,因为无论如何这些事件必须通过代码重新添加。)
所以最终的问题是Do_I_have_to_Load(tmpName)
如何工作?
网上有很多建议,一些建议在按钮点击后将动态控件存储在 Viewstate 中。 但在 Init 事件期间
- viewstate 是空的
- 所有控件(例如隐藏的文本框)都处于其初始状态(例如,为空)
所以忘记这个吧。 下一个想法是使用会话,但是
- 会话可能会过期
- 如何使用一个 session 变量处理多个窗口...
- 会话有很多开销
所以也忘记它吧。
为了找到解决方案,我只是查看了在Page_Init
期间可以访问的内容......答案是postbackdata
Function Do_I_have_to_Load(tmpName as String) as Boolean
If Not Request.Params( tmpName & "$myText") Is Nothing Then
return True
ElseIf Not Request.Params( tmpName & ":myText") Is Nothing Then
return True
ElseIf Not Request.Params( tmpName & "_myText") Is Nothing Then
return True
End If
return false
End Function
正如你所见,此解决方案使用Request.Param
集合来检查是否回发了属于动态控件的controlvalue
。(如果您已经在网上找到了这个技巧,请留下评论。)并且由于 .NET 根据 .NET 版本更改分隔符命名约定( _ 或 $ 或 : 作为分隔符),我测试了所有这些。
限制
在用户控件中查找控件名称(myText
)可能很糟糕,因为您必须确保myText
永远不会被隐藏。 考虑为此使用Input Type=Hidden
。
我没有包含一个用于“记住” controlID
和 ContainerID
的框架 ... 对它们进行硬编码,或者使用上面提到的 input type=hidden
方法?
历史
- 2009 年 7 月 20 日:初始版本; 一些拼写检查和澄清