控件的

时间:2016-12-19 12:55:58

标签: vb.net events panel handler

我正在使用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仍然没有...

1 个答案:

答案 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(通常通过紧密耦合的解决方案中的构造函数)。