Asp.net 动态创建的用户控件无法处理回发事件

Asp.net 动态创建的用户控件无法处理回发事件,asp.net,dynamic,user-controls,postback,Asp.net,Dynamic,User Controls,Postback,我有一个用户控件,它在页面的Init中使用以下代码动态加载到页面中 Dim oCtl As Object oCtl = LoadControl("~/Controls/UserControl1.ascx") oCtl.Id = "UserControl11" PlaceHolder1.Controls.Clear() PlaceHolder1.Controls.Add(oCtl) 用户控件还包含一个按钮,我无法捕获用户控件中的按钮单击 几个问题: 在页面生命周期的什么时候加载控件 事件处理程

我有一个用户控件,它在页面的Init中使用以下代码动态加载到页面中

Dim oCtl As Object
oCtl = LoadControl("~/Controls/UserControl1.ascx")

oCtl.Id = "UserControl11"
PlaceHolder1.Controls.Clear()
PlaceHolder1.Controls.Add(oCtl)
用户控件还包含一个按钮,我无法捕获用户控件中的按钮单击

几个问题:

  • 在页面生命周期的什么时候加载控件
  • 事件处理程序代码在哪里?在控件本身中,还是尝试将其连接到页面
  • 到目前为止,你做了些什么来筹备这次活动

  • 最后,.Net的风格指南特别建议不要使用任何hugarian前缀,比如oCtl中的o,并且您应该将其作为控件而不是对象键入。

    您只想在不回发时加载控件

    请确保在每次回发时加载控件-如果在回发页面时控件不在控件树中,ASP.NET将不会引发按钮单击事件

    在.NET进入页面生命周期的“回发事件处理”步骤之前,必须确保该控件存在于页面上。由于控件是动态添加的,因此您必须确保在每次回发时都重新创建该控件,以便它可以找到触发事件的控件。

    以下是页面的完整代码

    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
    

    下面是用户控件的完整代码

    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
    

    既然你问了,我就这样写你的init事件。我将把加载事件留作练习:

    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”更好的名字,但由于我不知道控件的作用,因此必须这样做。

    我不知道,但如果您通过编程连接按钮的事件处理程序,该怎么办?例如,在用户控件本身的代码隐藏中,在Init或Load(不确定)中:


    如果这样做没有任何作用,我知道这样做效率较低,但是如果您不在会话中存储用户控件实例,并且每次都在Page_Init中重新创建它,会怎么样?

    您正在做的一些事情都是不需要的,可能会导致您的问题

    这些是:

  • 不需要在会话中存储控件对象。控件本身应该使用ViewState和sessionstate来存储所需的信息,而不是整个实例
  • 创建控件时不应检查回发。每次都必须创建它,以允许ViewState工作并连接事件
  • 加载ViewState后加载的控件通常无法正常运行,因此尽可能避免在页面加载事件期间加载
  • 此代码适用于我:


    Default.aspx

    <%@ 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>
    

    UserControl1.ascx

    <%@ 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" />
    


    我遇到了与您类似的问题,只是我没有使用会话来存储控件

    在我的案例中,我将问题定位在这一行:

    placeholder 1.Controls.Clear()

    我所做的是创建一个子控件,并将它们添加到Page_Init上的父容器中,然后处理一些事件处理程序,然后在Page_PreRender上用更新的数据重新创建整个列表


    我在本例中使用的解决方案是在页面周期的早期阶段创建一次控件集合。

    接受匈牙利前缀的点应记住这一点,以备将来使用。我将在下面的注释中粘贴完整的代码。非常感谢您的反馈,但这实际上并不能在控制范围内解决我的反馈问题
    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
    
    <%@ 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" />
    
    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