2012-06-19 39 views
1

由於我目前正在處理的其他項目需要,因此我有一個程序集中的類。 一個類可以稱之爲Class Factory,創建一組需要附加點擊事件處理程序的控件,我有基於某些特徵來確定多態行爲的算法,但這是相對無關緊要的。 由於事件處理程序必須打開一個不屬於我的程序集的特定表單,並且該表單需要此「工廠」類。如果不創建循環引用,有什麼辦法可以基本上「委託」表單的處理程序事件來定義?將事件委託給表單而不創建循環引用

作爲一個簡單的解決方法,我不得不維護兩個獨立的類,一個在窗體項目中,另一個在程序集中。這顯然是錯誤的路要走。

不是100%確定的標題,因爲我知道我想做什麼,但不知道如何去做。

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
    Me.Width = 1500 
    Dim panel As New Panel 
    panel.Location = New Point(0, 0) 
    panel.Size = New Size(1000, 200) 
    panel.BackColor = Color.Yellow 
    Me.Controls.Add(panel) 
    Dim factory As New DrawFactory 
    factory.DrawPanel(panel, 5) 
End Sub 

以上是在一個單獨的項目,下面的代碼是在類庫:

Public Class DrawFactory 
Private xOffset As Integer = 0 
Private Const widthConst As Integer = 50 
Public Sub DrawPanel(ByRef panel As Panel, ByVal drawPanels As Integer) 
    Application.DoEvents() 
    For i As Integer = 0 To drawPanels 
     Dim childPanel As New Panel 
     childPanel.Location = New Point(xOffset, 0) 
     childPanel.Size = New Size(widthConst, panel.Height) 
     If i < 1 Then 
      childPanel.BackColor = Color.Blue 
     Else 
      childPanel.BackColor = Color.Pink 
     End If 
     xOffset = xOffset + widthConst 
     ''want to add a handler here to open say form5 which is unknown and undefined in the scope of this class 
     panel.Controls.Add(childPanel) 
    Next 
End Sub 
End class 

這不是我的實際代碼,但它描繪的是我的問題JIST米麪臨,我不介意在C#或VB.NET中的答案。

+0

請處理一個簡單的虛構示例來說明您的問題。 –

+0

@SteveDog我已經按要求添加了一個示例 – Tyson

+0

您是否嘗試將表單上存在的事件處理程序添加到childPanels上的事件?如果是這樣,哪個事件? –

回答

1

循環引用在技術上不是.NET中的問題。這是COM中的問題,因爲COM使用引用計數來確定何時需要銷燬對象。如果您有兩個彼此相互引用的對象,則循環引用不會導致對象的引用計數達到零,因此它們永遠不會被銷燬(導致內存泄漏)。但是,在.NET中,CLR使用垃圾收集而不是引用計數。垃圾回收器會定期搜索所有對象以查找應用程序不再引用的對象。然後破壞所有那些如果發現的死物。垃圾回收器足夠聰明,可以知道兩個或多個只能相互引用的對象,而沒有其他東西都是死的。因此,在.NET託管代碼中,循環引用不再導致內存泄漏,因此不再需要避免。

但是,這就是說,是的,您可以將事件處理程序方法作爲委託傳遞給另一個項目中的DrawFactory類。然後DrawFactory類可以將該事件處理程序添加到它想要的任何事件中。例如:

Public Sub DrawPanel(ByVal panel As Panel, ByVal drawPanels As Integer, ByVal handler As EventHandler) 
    For i As Integer = 0 To drawPanels 
     Dim childPanel As New Panel 
     '... 
     AddHandler panel.Click, handler 
     panel.Controls.Add(childPanel) 
    Next 
End Sub 

然後,你的表格上,你需要一個的事件處理程序的簽名,如匹配方法:

Private Sub Panel_Click(ByVal sender As Object, ByVal e As EventArgs) 
    Form2.Show() 
End Sub 

然後你可以調用工廠是這樣的:

factory.DrawPanel(panel, 5, New EventHandler(AddressOf Panel_Click)) 
+0

這樣做,非常感謝! – Tyson

0

是的,我相信你可以做到這一點。單擊事件的簽名看起來是這樣的:

private void ButtonOkClicked(object sender, RoutedEventArgs e) 
{ 

} 

你的類工廠創建方法可能需要在行動,所以:

void Create(Action<object, RoutedEventArgs> clickAction) 
{ 
    var btn = new Button(); 
    btn.OnClick += clickAction; 
} 

我希望這可以幫助,請讓我知道,如果它不。

+0

如果有幫助,我已經添加了一個示例,請注意我正在使用WinForms。 「RoutedEventArgs」未被intellisense檢測到,除非我遺漏了導入/引用。雖然我相信你正確理解我的問題。 – Tyson

+0

對不起,我正在假設WPF。我很高興你解決了這個問題。 – Dave