我正在使用VB .NET来创建计划,我对事件有点问题。 在主窗体中,我放置了一个面板,我在其中以编程方式在这些行中添加行和框。我在表单内部有一个TextBox和包含所有框的面板。我想在单击一个框时更改TextBox的文本,所以我使用AddHandler语句但它不起作用。我试图调试它,我意识到它实际上调用了sub和它内部,我可以看到它所做的更改(TextBox.Text成为我想要的),但当它退出sub时,它就像没有任何改变。 我不知道我是否足够清楚。 感谢
这是一个简化的代码(我删除了所有图形函数以调整控件的大小......)
Public Class frmPrinc
Public actEditing As Object
Private Class boxAct
Inherits Label
Public act As Integer
Public Sub New(ByVal a As Integer)
act = a
AddHandler Me.Click, AddressOf clickBox
End Sub
Private Sub clickBox(sender As Object, e As EventArgs)
Dim boxact As boxAct = DirectCast(sender, boxAct)
frmPrinc.actEditing = boxact
boxact.Text = "Clicked"
End Sub
End Class
Private Sub showPlanning()
pan_plan.Controls.Clear()
Dim plan As New Control ' Control that will be used as a row
For i As Integer = 0 To 10
plan.Controls.Add(New boxAct(i))
Next
Panel1.Controls.Add(plan)
End Sub
End Class
当我运行它时,框的文本会发生变化但是actEditing仍然没有...
答案 0 :(得分:1)
而不是boxAct尝试直接更新当前"框中的frmPrinc"点击它,它应该提出frmPrinc订阅的自定义事件。 frmPrinc可以使用该信息,因为它认为合适。下面我添加了自定义事件并在类boxAct中提升它。在创建每个boxAct实例时,表单使用AddHandler订阅该事件。总之,这看起来像是:
Public Class frmPrinc
Public actEditing As boxAct
Public Class boxAct
Inherits Label
Public act As Integer
Public Event BoxClicked(ByVal box As boxAct)
Public Sub New(ByVal a As Integer)
act = a
End Sub
Private Sub boxAct_Click(sender As Object, e As EventArgs) Handles Me.Click
Me.Text = "Clicked"
RaiseEvent BoxClicked(Me)
End Sub
End Class
Private Sub showPlanning()
pan_plan.Controls.Clear()
Dim plan As New Control ' Control that will be used as a row
For i As Integer = 0 To 10
Dim box As New boxAct(i)
AddHandler box.BoxClicked, AddressOf box_BoxClicked
plan.Controls.Add(box)
Next
Panel1.Controls.Add(plan)
End Sub
Private Sub box_BoxClicked(box As boxAct)
actEditing = box
Debug.Print("Box Clicked: " & actEditing.act)
End Sub
End Class
来自评论:
谢谢你,它有效!我想知道为什么我需要这样做 用于引发修改主窗体的简单事件的结构... 只是为了不再犯同样的错误 - Algor Frile
这是每个人都必须做出的设计决定:"Loosely Coupled" vs. "Tightly Coupled"。我上面给出的方法属于 Loosely Coupled 类别。松散耦合解决方案的主要好处是可重用性。在您的特定情况下,我们将Class boxAct重复使用多次,尽管它们都在同一个表单中。但是如果不是这样呢?如果您想在多个表单上使用boxAct(甚至有多个"组"),该怎么办?使用您的原始方法,您有这一行:
frmPrinc.actEditing = boxact
这意味着如果想要使用具有不同表单的Class boxAct,您必须复制Class boxAct,给它一个新名称,然后手动更改该行以引用新表单: / p>
Public Class boxAct2
Private Sub clickBox(sender As Object, e As EventArgs)
Dim boxact As boxAct = DirectCast(sender, boxAct)
frmSomeOtherForm.actEditing = boxact
boxact.Text = "Clicked"
End Sub
End Class
这显示了紧密耦合方法的缺点,它使用对特定类型(在本例中为Form)的引用进行通信。当您快速和激烈地编码时,紧密耦合的方法可能最初更容易实现,但随后它会再次出现可重用性。在某些情况下,紧密耦合的解决方案是有意义的,但只有您可以做出决定;这些场景通常涉及某种“控制”和#34;只会在某种自定义容器/控件中使用,并且永远不会在其他地方使用。
相反,使用松散耦合的方法,如果我们想以不同的形式重新使用Class boxAct,那么根本不需要不需要更改(尽管那时你是&#39 ; d可能不希望在原始表格中声明它!)。在新表单中,您只需为BoxClicked()事件添加处理程序,然后执行您需要执行的操作。每个表单都会收到其各自boxAct实例的事件。
最后的想法...你的原始方法实际上可行,但很可能在这一行失败(与上面相同):
frmPrinc.actEditing = boxact
在这里,您使用该表单的 Default Instance 引用了frmPrinc。如果frmPrinc是" Startup Object"这将起作用。为您的应用程序。不过,我猜测它不是,而你正在从其他地方创建一个frmPrinc实例。要使原始方法有效,您必须将对frmPrinc 的ACTUAL实例的引用传递给Class boxAct(通常通过紧密耦合的解决方案中的构造函数)。