«Повторное возбуждение» пользовательских событий в .NET (в данном случае ASP.NET) - PullRequest
3 голосов
/ 02 декабря 2008

Я работаю на странице ASP.NET, использую VB.NET, и у меня есть эта иерархия:

Страница A
- Веб-контроль пользователя 1
- Веб-контроль пользователя A
- Веб-контроль пользователя B
- Веб-контроль пользователя C

Мне нужно вызвать событие из пользовательского веб-элемента управления B, которое получит страница A (поток событий будет представлять собой веб-элемент управления B -> пользовательский веб-элемент управления 1 -> страница A).

Мой единственный подход был таким: 1) Добавьте объявление пользовательского события как в пользовательский веб-элемент управления B, так и в пользовательский веб-элемент управления 1, и просто дважды поднимите RaiseEvent, пока он не попадет на страницу A (это выглядит некрасиво, и мне это не особо нравится).

Моя другая идея состояла в том, чтобы создать собственный класс Event, который наследуется от некоторого магического базового класса Event, и создать его экземпляр как в Web User Control B, так и в Web User Control 1, но это оказалось бесплодным, потому что я не могу найти любые базовые классы событий (может быть, они не являются какими-либо другими, поскольку это ключевое слово, а не имя класса).

Любая помощь будет оценена! Спасибо и счастливого кодирования!

Ответы [ 4 ]

4 голосов
/ 02 декабря 2008

Вы можете использовать концепцию BubbleEvent для этого. BubbleEvent поднимается вверх по иерархии управления, пока кто-то не обработает его. Элементы управления GridView и Repeater делают это со своими событиями Row / ItemCommand.

Вы можете реализовать его в WebUserControl1, превратив его в стандартное событие для страницы (как это делает GridView):

Class UserControl1 ' Parent
   Protected Override Function OnBubbleEvent(sender as Object, e as EventArgs) as Boolean
       Dim c as CommandEventArgs = TryCast(e, CommandEventArgs)
       If c IsNot Nothing Then
           RaiseEvent ItemEvent(sender, c)
           Return True ' Cancel the bubbling, so it doesn't go up any further in the hierarchy
       End If
       Return False ' Couldn't handle, so let it bubble
   End Function

   Public Event ItemEvent as EventHandler(Of CommandEventArgs)
End Class

Class UserControlB ' Child
    Protected Sub OnClicked(e as EventArgs)
        ' Raise a direct event for any handlers attached directly
        RaiseEvent Clicked(Me, e)
        ' And raise a bubble event for parent control
        RaiseBubbleEvent(Me, New CommandEventArgs("Clicked", Nothing))
    End Sub

    Protected Sub OnMoved(e as EventArgs)
        ' Raise a direct event for any handlers attached directly
        RaiseEvent Moved(Me, e)
        ' And raise a bubble event for parent control
        RaiseBubbleEvent(Me, New CommandEventArgs("Moved", Nothing))
    End Sub
End Class

Class PageA
    Sub UserControl1_ItemEvent(sender as Object, e as CommandEventArgs) Handles UserControl1.ItemEvent
        Response.Write(sender.GetType().Name & " was " & e.CommandName)
    End Sub
End Class

Или сделайте это прямо на странице. UserControlB (Child) - то же самое, что и выше, и UserControl1 (Parent) не должен делать ничего особенного - OnBubbleEvent по умолчанию возвращает False, поэтому событие всплывает:

Class PageA
   Protected Override Function OnBubbleEvent(sender as Object, e as EventArgs) as Boolean
       If sender Is UserControlB Then
           Dim c as CommandEventArgs = TryCast(e, CommandEventArgs)
           If c IsNot Nothing Then
               Response.Write(sender.GetType().Name & " was " & c.CommandName)
           Else
               Response.Write(sender.GetType().Name & " raised an event, with " & e.GetType().Name & " args)
           End If
           Return True ' Cancel the bubbling, so it doesn't go up any further in the hierarchy
       End If
       Return False ' Not handled
   End Function
End Class

Если ваше первоначальное событие происходит от серверного элемента управления (например, Button.Click), то оно будет закодировано, чтобы уже вызывать событие пузыря - поэтому UserControlB (Child) не нужно ничего делать, чтобы передать это родитель тоже. Вам просто нужно вызвать RaiseBubbleEvent для любого из ваших пользовательских событий или если вы хотите каким-то образом преобразовать EventArgs.

1 голос
/ 02 декабря 2008

Создать сборку (или пространство имен), на которое ссылается все. Создайте интерфейс с нужными вам методами. Создайте класс, который управляет объектами, которые реализовали интерфейс.

Имейте страницу А, чтобы реализовать интерфейс Сделайте так, чтобы Страница A зарегистрировалась в классе менеджера, сделанном на шаге 3 Теперь Web UserControl B может вызывать событие, извлекая страницу из менеджера и вызывая метод в интерфейсе, который вызывает нужное вам событие.

Вы избегаете тесной связи страницы с веб-контролем, потому что используете интерфейс.

Вероятно, вы обнаружите, что у вас будет несколько интерфейсов для разных областей вашего проекта. Например, в моем проекте CAM у меня есть интерфейс для пользовательского интерфейса параметров настройки, пользовательского интерфейса Shape Entry и пользовательского интерфейса Cut Entry. На нашем сайте у нас есть разные категории продуктов, которые используют разные интерфейсы. (Программное обеспечение, машины, услуги и т. Д.).

1 голос
/ 02 декабря 2008

Реальный вопрос здесь заключается в том, является ли действительное действие в Web UserControl B чем-то, что должно сообщать обоим, ИЛИ, является ли WebUserControl1 ответственным за некоторую обработку ПЕРЕД уведомлением страницы.

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

0 голосов
/ 02 декабря 2008

Вы можете создать открытый метод в Page A, который вызывается из Web User Control B вместо того, чтобы вызывать событие во всем дереве управления.

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

Пример страницы:

Public Partial Class TestPage
    Inherits Page

    Public Sub PerformAction()
        'Whatever needs to be done on Page A
    End Sub
End Class

Пример пользовательского контроля:

Public Partial Class TestControl
    Inherits UserControl

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        'This will call the Page, obviously this will only
        'work when the control is on TestPage
        CType(Page, TestPage).PerformAction()
    End Sub
End Class
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...