2012-06-19 33 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