65.9K
CodeProject 正在变化。 阅读更多。
Home

动态加载的控件:轻松实现

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.60/5 (2投票s)

2009年7月20日

MIT

3分钟阅读

viewsIcon

14513

非臃肿的方式重新加载动态加载的控件,并保持事件处理完好。

引言

当使用动态加载的控件(通过使用.loadcontrol()方法)时,需要考虑多个方面,特别是需要解决以下三个问题。

  1. 控件在回发后不能消失(第一个问题)
  2. 控件的内容必须被保留(第二个问题)
  3. 控件内的事件必须仍然触发(第三个问题)

此处最重要的是第 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_LoadtmpName

解决第二个问题

这一个是简短的:上面代码中有一行

 tempcontrol.ID = tmpName

您所要做的就是始终为相同的控件提供相同的 ID。 然后ViewstatePostback数据将被保留。(这很容易,并且在许多其他文章中都有提到。)

解决第三个问题

这是本文的核心,尽管它已经在上面的代码中解决了,当我提到使用 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

我没有包含一个用于“记住” controlIDContainerID 的框架 ... 对它们进行硬编码,或者使用上面提到的 input type=hidden 方法?

历史

  • 2009 年 7 月 20 日:初始版本; 一些拼写检查和澄清
© . All rights reserved.