我有一个用户控件,它使用页面初始化中的以下代码动态加载到页面中。
1 2 3 4 5 6
| Dim oCtl As Object
oCtl = LoadControl("~/Controls/UserControl1.ascx")
oCtl.Id ="UserControl11"
PlaceHolder1.Controls.Clear()
PlaceHolder1.Controls.Add(oCtl) |
用户控件还包含一个按钮,我无法捕获用户控件中的按钮单击。
您正在做的一些事情既不需要,也可能会导致您的问题。
这些是:
无需将控制对象存储在会话中。控件本身应该根据需要使用 ViewState 和 Session State 来存储信息,而不是整个实例。
创建控件时不应检查 PostBack。每次都必须创建它以允许 ViewState 工作和连接事件。
在加载 ViewState 后加载的控件通常无法正常运行,因此请尽可能避免在 Page Load 事件期间加载。
此代码适用于我:
默认.aspx
1 2 3 4 5 6 7 8 9 10
| %@ Page Language="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb" Inherits="Test_User_Control._Default" %
!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
html xmlns="http://www.w3.org/1999/xhtml"
head runat="server"title/title/head
body
form id="form1" runat="server"
asp:PlaceHolder ID="PlaceHolder1" runat="server" /
/form
/body
/html |
默认.aspx.vb
1 2 3 4 5 6 7 8 9 10
| Partial Public Class _Default
Inherits System.Web.UI.Page
Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
Dim control As Control = LoadControl("~/UserControl1.ascx")
PlaceHolder1.Controls.Add(control)
End Sub
End Class |
UserControl1.ascx
1 2 3
| %@ Control Language="vb" AutoEventWireup="false" CodeBehind="UserControl1.ascx.vb" Inherits="Test_User_Control.UserControl1" %
asp:Label ID="Label1" Text="Before Button Press" runat="server" /
asp:Button ID="Button1" Text="Push me" runat="server" / |
UserControl1.ascx.vb
1 2 3 4 5 6 7 8
| Public Partial Class UserControl1
Inherits System.Web.UI.UserControl
Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text ="The button has been pressed!"
End Sub
End Class |
在 .NET 进入页面生命周期的"回发事件处理"步骤之前,您必须确保该控件存在于页面上。由于控件是动态添加的,因此您必须确保在每次回发时重新创建该控件,以便它可以找到触发事件的控件。
确保在每次回发时都加载控件 - 如果页面回发时控件不在控件树中,ASP.NET 将不会引发按钮单击事件。
我刚刚遇到了与您类似的问题,除了在我的情况下我没有使用会话来存储控件。
就我而言,我在这一行中找到了问题:
PlaceHolder1.Controls.Clear()
我所做的是创建一个子控件并将它们添加到 Page_Init 上的父容器中,然后处理一些事件处理程序,然后在 Page_PreRender 上我再次使用更新的数据重新创建整个列表。
我在这种情况下使用的解决方案是在页面周期的早期阶段创建一次控件集合。
几个问题:
在页面生命周期的什么时候加载控件?
事件处理程序代码在哪里?在控件本身还是您尝试将其连接到页面?
到目前为止,你做了什么来完成这个活动?
最后,.Net 的样式指南特别建议不要在 oCtl 中使用任何像 o 这样的匈牙利前缀疣,您应该将其键入为控件而不是对象。
如果不尝试,我不知道,但是如果您以编程方式连接按钮的事件处理程序会怎样?例如,在用户控件本身的代码隐藏中,在 Init 或 Load 中(不确定):
1
| AddHandler Button1.Click, AddressOf Button1_Click |
如果这不起作用,我知道它的效率较低,但是如果您不将用户控件实例存储在 Session 中并且每次都在 Page_Init 中重新创建它怎么办?
既然你问了,我会这样写你的初始化事件。我将把 Load 事件留作练习:
1 2 3 4 5 6
| Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
If IsPostBack AndAlso Session("ctl") IsNot Nothing Then
Dim MyControl As Control = Session("ctl")
PlaceHolder1.Controls.Add(MyControl)
End If
End Sub |
我也会想出一个比"mycontrol"更好的名字,但是因为我不知道这个控件会做什么。
这是页面的完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| Partial Class DynamicLoad
Inherits System.Web.UI.Page
Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
If IsPostBack Then
If Not (Session("ctl") Is Nothing) Then
Dim oCtl As Object
oCtl = Session("ctl")
PlaceHolder1.Controls.Add(oCtl)
End If
End If
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim oCtl As Object
oCtl = LoadControl("~/Controls/UserControl1.ascx")
oCtl.Id ="UserControl11"
PlaceHolder1.Controls.Clear()
PlaceHolder1.Controls.Add(oCtl)
Session("ctl") = oCtl
End If
End Sub
End Class |
这里是用户控件的完整代码
1 2 3 4 5 6
| Partial Class UserControl1
Inherits System.Web.UI.UserControl
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text ="This is Text AFTER Post Back in User Control 1"
End Sub
End Class |
您只想在不是时加载控件 isPostBack