Need help translating C# to VB

2019-07-17 04:21发布

问题:

I am looking at this blog, and I am trying to translate the snippet to VB.

I'm having difficulties with this line:

NotifyCollectionChangedEventHandler handlers = this.CollectionChanged;

NOTE: CollectionChanged is an event of this ('this' is an override of ObservableCollection<T>).

回答1:

To raise the event, OnCollectionChanged should work fine. If you want to query it you have to get more abusive and use reflection (sorry, example is C# but should be virtually identical - I'm not using any language-specific features here):

NotifyCollectionChangedEventHandler handler = (NotifyCollectionChangedEventHandler)
    typeof(ObservableCollection<T>)
    .GetField("CollectionChanged", BindingFlags.Instance | BindingFlags.NonPublic)
    .GetValue(this);

et voila; the handler or handlers (via GetInvocationList()).

So basically in your example (regarding that post), use:

Protected Overrides Sub OnCollectionChanged(e As NotifyCollectionChangedEventArgs)
    If e.Action = NotifyCollectionChangedAction.Add AndAlso e.NewItems.Count > 1 Then
        Dim handler As NotifyCollectionChangedEventHandler = GetType(ObservableCollection(Of T)).GetField("CollectionChanged", BindingFlags.Instance Or BindingFlags.NonPublic).GetValue(Me)
        For Each invocation In handler.GetInvocationList
            If TypeOf invocation.Target Is ICollectionView Then
                DirectCast(invocation.Target, ICollectionView).Refresh()
            Else
                MyBase.OnCollectionChanged(e)
            End If
        Next
    Else
        MyBase.OnCollectionChanged(e)
    End If
End Sub


回答2:

Literally, it should be something like

Dim handlers As NotifyCollectionChangedEventHandler = AddressOf Me.CollectionChanged

(can't tell since I don't know the exact types)

But note that you raise events in VB using RaiseEvent



回答3:

Duh. After having finally seen and read the blog posting you linked, here’s the answer:

In VB, you need to declare a custom event to override the RaiseEvent mechanism. In the simplest case, this looks like this:

Private m_MyEvent As EventHandler

Public Custom Event MyEvent As EventHandler
   AddHandler(ByVal value as EventHandler)
      m_MyEvent = [Delegate].Combine(m_MyEvent, value)
   End AddHandler

   RemoveHandler(ByVal value as EventHandler)
      m_MyEvent = [Delegate].Remove(m_MyEvent, value)
   End RemoveHandler
   RaiseEvent(sender as Object, e as EventArgs)
      Dim handler = m_MyEvent

      If handler IsNot Nothing Then
          handler(sender, e)
      End If
   End RaiseEvent
End Event

In your case, the RaiseEvent routine is slightly more involved to reflect the additional logic, but the gist remains the same.