【问题标题】:in vb.net how do I raise an event of another control在 vb.net 中如何引发另一个控件的事件
【发布时间】:2014-01-07 17:08:48
【问题描述】:

我看到的每个示例都是关于鼠标单击的,然后示例是相同的。

我需要专门在另一个控件上引发事件。

我有一个面板,其中包含我这样创建的事件:

Private FlowPanel as new my_FlowLayoutPanel
Addhandler FlowPanel.change, addressof doChange

    Public Class my_FlowLayoutPanel
            Inherits FlowLayoutPanel

            Public Event change(ByVal sender As Object)
            Public Const Ver_SCROLL As Integer = &H115

            Protected Overrides Sub WndProc(ByRef m As Message)
                If m.Msg = Ver_SCROLL Then
                    RaiseEvent change(Me)
                End If

                MyBase.WndProc(m)
            End Sub
        End Class

所以当垂直滚动条移动时,“change”事件就会触发。

所以现在,我有另一个控件,(一个简单的面板)设置如下:

Public Class view_Panel
        Inherits System.Windows.Forms.Panel

        Protected Overrides Sub WndProc(ByRef m As Message)

            Const NCMOUSEMOVE As Integer = &H200

            If m.Msg = NCMOUSEMOVE Then

              ' *** FIRE THE "CHANGE" EVENT ON THE FLOWLAYOUT PANEL

            End If
            MyBase.WndProc(m)
        End Sub

    End Class

那么,如何从 view_Panel 触发“Change”事件?

【问题讨论】:

  • 这些控件在表单上如何相互关联?
  • my_FlowLayoutPanel 驻留在哪里?

标签: vb.net events


【解决方案1】:

即使在阅读了其他答案之后,例如上面的“Pouya Samie”(如果有的话,请反映到OnChange),或者这篇更增强的文章“Raising Events Using Reflection”看起来更干净但并不总是有效(反映到@987654323 @)...

所以终于把我所有的想法都整理好了,让一个通用方法简单的语法来执行这个任务:

TriggerEvent(ComboBox1, "OnSelectedIndexChanged")

请注意,上述方法在 ComboBox1 内是private non-accesible,它甚至在 IntelliSense 列表成员中未列出,但使用这种反射方法它会起作用好的:

''' <summary>
''' Manually trigger an existing event in a control.
''' </summary>
''' <param name="ctrlObject">The GUI control that that should be operated (such as ComboBox).</param>
''' <param name="onEventName">The OnEvent function regardless of the scope (such as OnSelectedIndexChanged).</param>
''' <returns><code>True</code> when the method is found invoked and returned successfully; <code>false</code> otherwise.</returns>
Public Function TriggerEvent(ctrlObject As Control, onEventName As String) As Boolean

    ' Get the reference to the method
    Dim methodRef As MethodInfo = ctrlObject.GetType().GetMethod(onEventName, _
            System.Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.Static Or _
            System.Reflection.BindingFlags.Instance)
    If IsNothing(methodRef) Then Return False

    ' Invoke the method
    Try
        methodRef.Invoke(ctrlObject, New Object() {EventArgs.Empty})
        Return True
    Catch ex As Exception
        Return False
    End Try

End Function

【讨论】:

    【解决方案2】:

    编辑 要从另一个类调用您的事件,您可以使用反射

     MethodInfo onchange = YourClassInstance.GetType().GetMethod("OnChange",              System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        onChange.Invoke(YourClassInstance, new object[] { new EventArgs() });
    

    【讨论】:

    • 虽然是一篇好文章,但它没有提到引发其他控件的事件。
    • 查看我的更新答案中的步骤 2 和 3
    • 你刚刚复制了这篇文章,复制到这里。复制后,没有任何变化。所以我的问题仍然存在:你会在我的程序中插入什么代码,上面写着“' *** FIRE THE "CHANGE" EVENT ON THE FLOWLAYOUT PANEL”?
    • 要从声明类外部引发事件,您必须派生类并添加公共包装方法
    • 第 2 步创建了一个名为 Sender 的类和一个名为 Start 的事件,然后第 3 步只是在同一个类中触发 Start 事件。如果我对我的代码使用相同的逻辑,那么我会用“RaiseEvent change()”代替我的代码,我会收到错误:“change”不是 view_Panel 的事件。
    【解决方案3】:

    你可能想要这样的东西:

    Case WM_HSCROLL
         RaiseEvent Scroll(Me, New ScrollEventArgs(ScrollEventType.EndScroll, _
               Win32.GetScrollPos(Me.Handle, Win32.SBOrientation.SB_HORZ), _ 
               ScrollOrientation.HorizontalScroll))
    
    Case WM_VSCROLL
         RaiseEvent Scroll(Me, New ScrollEventArgs(ScrollEventType.EndScroll, _
               Win32.GetScrollPos(Me.Handle, Win32.SBOrientation.SB_VERT), _
               ScrollOrientation.VerticalScroll))
    

    ScrollEventArgs 是一个标准的网络事件,所以我们不需要定义它。然后将事件声明为('change' 似乎是一个非常糟糕的选择):

    Public Event Scroll(ByVal sender As Object, ByVal sa As ScrollEventArgs)
    

    如果您的 Panel 需要对事件做一些事情,请使用 OnScroll 方法,该方法允许面板在最终订阅者收到事件之前做一些事情:

    Protected Overrides Sub OnScroll(ByVal sa As ScrollEventArgs)
        ... do stuff
        ' in cases where you no longer need the event to be passed
        ' on, dont call this:
        MyBase.OnScroll(e)
    End Sub
    

    使用方法:

    由于您将两者子类化,让 Panel 引发事件,FlowPanel 可以监视这些事件(订阅面板的滚动事件),并在此执行您在Change 中要做的任何事情。由于 ACTION 发生在面板中/面板上,因此最好只在那里处理。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多