Пользовательский элемент управления, созданный динамически, не может обрабатывать события в PostBack - PullRequest
6 голосов
/ 18 сентября 2008

У меня есть пользовательский элемент управления, который динамически загружается на страницу, используя следующий код в Init страницы.

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

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

Пользовательский элемент управления также содержит кнопку, и я не могу зафиксировать нажатие кнопки в пользовательском элементе управления.

Ответы [ 9 ]

10 голосов
/ 14 октября 2008

Есть пара вещей, которые вы делаете, которые не нужны и, вероятно, вызывают ваши проблемы.

Это:

  1. Нет необходимости хранить объект управления в сеансе. Сам элемент управления должен использовать ViewState и Session State для хранения необходимой информации, а не всего экземпляра.
  2. Вы не должны проверять PostBack при создании элемента управления. Он должен создаваться каждый раз, чтобы позволить и ViewState работать, и событию быть связанным.
  3. Элементы управления, загруженные после загрузки 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>

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

UserControl1.ascx.vb

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 голосов
/ 18 сентября 2008

Необходимо убедиться, что элемент управления существует на странице, прежде чем .NET перейдет к шагу «Обработка события обратной передачи» жизненного цикла страницы. Поскольку элемент управления добавляется динамически, вы должны убедиться, что на каждом посте обратно вы воссоздаете этот элемент управления, чтобы он мог найти элемент управления для запуска события.

3 голосов
/ 18 сентября 2008

Убедитесь, что вы загружаете элемент управления при каждой обратной передаче - если элемент управления не находится в дереве элементов управления при отправке страницы назад, ASP.NET не будет вызывать событие нажатия кнопки.

2 голосов
/ 13 февраля 2009

Я только что столкнулся с той же проблемой, что и вы, за исключением того, что в моем случае я не использовал сеанс для хранения элемента управления.

В моем случае я обнаружил проблему в этой строке:

PlaceHolder1.Controls.Clear()

Я создал дочерние элементы управления и добавил их в родительский контейнер в Page_Init, затем обработал некоторые обработчики событий и после этого в Page_PreRender заново создал весь список с обновленными данными.

Решение, которое я использовал в этом случае, состояло в том, чтобы создать коллекцию элементов управления один раз - на ранней стадии цикла страницы.

1 голос
/ 18 сентября 2008

Несколько вопросов:

  1. В какой момент жизненного цикла страницы вы загружаете элемент управления?
  2. Где находится код обработчика события? В самом элементе управления или вы пытаетесь подключить его к странице?
  3. Что вы уже сделали, чтобы подключить мероприятие?

Наконец, правила стилей для .Net особенно рекомендуют против с использованием любых бородавок с префиксом hugarian, таких как o в oCtl, и вы должны ввести его как элемент управления, а не как объект.

0 голосов
/ 18 сентября 2008

Не знаю, не попробовав, но что, если вы программно подключите обработчик событий кнопки? Например, в коде для самого пользовательского элемента управления в Init или Load (не уверен):

AddHandler Button1.Click, AddressOf Button1_Click

Если это ничего не дает, я знаю, что это менее эффективно, но что если вы не сохраните экземпляр пользовательского элемента управления в сеансе и не будете каждый раз заново создавать его в Page_Init?

0 голосов
/ 18 сентября 2008

Так как вы спросили, я бы написал ваше событие инициации вот так. Я оставлю событие 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», но, поскольку я не знаю, что делает элемент управления, это будет делать.

0 голосов
/ 18 сентября 2008

Вот полный код страницы

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 голосов
/ 18 сентября 2008

Вы хотите загружать элемент управления, только если не isPostBack

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...