动态创建的用户控件无法在回发时处理事件

6

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

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

oCtl.Id = "UserControl11"
PlaceHolder1.Controls.Clear()
PlaceHolder1.Controls.Add(oCtl)

用户控件还包含一个按钮,但我无法在用户控件内捕获按钮点击事件。
9个回答

10

您正在做的几件事情既没有必要,而且可能会导致问题。

这些是:

  1. 没有必要在会话中存储控件对象。控件本身应使用ViewState和Session State根据需要存储信息,而不是整个实例。
  2. 在创建控件时不应检查PostBack。每次都必须创建控件,以允许ViewState工作并连接事件。
  3. 在ViewState加载后加载的控件通常很难正常运行,因此请尽可能避免在Page Load事件期间进行加载。

这段代码对我有效:


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>

Default.aspx.vb

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

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


5

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


3

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


2

我刚刚遇到了和你类似的问题,只是在我的情况下,我没有使用会话来存储控件。

在我的情况下,我发现问题出在这一行:

PlaceHolder1.Controls.Clear()

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

在这种情况下,我使用的解决方案是在页面周期的早期阶段创建控件集合。


1

几个问题:

  1. 在页面生命周期的哪个阶段加载控件?
  2. 事件处理程序代码在哪里?在控件本身还是尝试将其连接到页面上?
  3. 你已经做了什么来连接事件?

最后,.Net的样式指南特别建议不要使用任何匈牙利前缀,例如oCtl中的o,而应该将其键入为Control而不是对象。


点收到了匈牙利前缀,将来会记住的。我将在下面的评论中粘贴完整的代码。感谢您的反馈。 - Eggs McLaren

0
我不确定,但如果您以编程方式连接按钮的事件处理程序会怎样呢?例如,在用户控件本身的代码后台中,在Init或Load(不确定)中:
AddHandler Button1.Click, AddressOf Button1_Click

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


0

这是页面的完整代码

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

0

既然你问了,我会这样编写您的初始化事件。Load事件就留给你做练习吧:

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”更好的名称,但由于我不知道这个控件的作用,所以只能这样了。

但这并没有真正解决我在控件内的回发问题。 - Eggs McLaren

-1

你想在非PostBack时才加载控件


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接