2008-12-02 69 views
3

我工作的ASP.NET頁面上,使用VB.NET和我有這樣的層次:「再提高」使用.NET自定義事件(ASP.NET在這種情況下)

頁A
    - Web用戶控件1個
        - Web用戶控制
        - Web用戶控件乙
        - 網頁用戶控件C

我需要從網頁用戶控件B提出一個事件,網頁A將收到(事件流將是網頁用戶控件B - >網頁用戶控件1 - >頁面A)。

我到目前爲止唯一的方法是這樣的: 1)向Web用戶控件B和Web用戶控件1添加一個自定義事件聲明,並簡單地將RaiseEvent兩次添加到頁面A中(這看起來很醜陋,特別喜歡它)。

我的另一個想法是創建一個自定義的Event類,它從一些神奇的基類事件類中獲取,並在Web用戶控件B和Web用戶控件1中創建它的一個實例,但這證明是徒勞的,因爲我不能找到任何事件基類(可能他/她沒有,因爲它似乎是一個關鍵字,而不是類名)。

任何幫助,將不勝感激!感謝和快樂的編碼!

回答

4

您可以使用BubbleEventconcept來執行此操作。一個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(兒童)是與上面相同,和的UserControl1(母公司)並不需要做什麼特別的 - 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。

+0

這正是我試圖找出如何去做的。完美的答案!非常感謝(其他人也很好的回答)。 – 2008-12-02 18:15:33

1

這裏真正的問題是Web UserControl B中的實際操作應該通知這兩者,或者是WebUserControl1負責在通知頁面之前進行一些處理。

如果鏈條的每一步都有特定的動作,那麼提升兩個事件的方法是正確的。如果事件只是需要通知所有人,您需要查看不同的訂閱方式進行通信。

0

您可以在Page A中創建一個公共方法,該方法從Web User Control B調用,而不是在整個控件樹中引發事件。

這不會是我的第一選擇,因爲這會導致這些類之間的緊密耦合,但我希望它能解決您的問題。

示例頁面:

樣品用戶控制:

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 
1

創建大會(或命名空間)是由所有引用。 用你需要的方法創建一個接口。 創建一個管理實現該接口的對象的類。

有無頁A實現接口 有無頁A註冊本身與步驟#3 現在的Web用戶控件乙完成的經理類可以通過從管理器檢索頁面並調用提高了接口的方法引發事件你需要的事件。

由於使用的是接口,因此避免將頁面緊密耦合到webcontrol。

可能你會發現你將有一個多接口的項目的不同領域。例如,在我的CAM項目中,我有一個用於設置參數UI,Shape Entry UI和Cut Entry UI的界面。在我們的網站上,我們有使用不同界面的不同產品類別。 (軟件,機械,服務等)。