3
\$\begingroup\$

I have multiple menus that will change languages in one Sub that will handle multiple events of the menus click, It is working for me right now, I'm just wondering if there is better way to do it... I'm using the menus name to call the process for each menus.

    Private Shared Sub CheckMenuItem(ByVal mnu As ToolStripMenuItem, ByVal checked_item As ToolStripMenuItem)

    For Each menu_item As ToolStripMenuItem In mnu.DropDownItems.OfType(Of ToolStripMenuItem)()
        menu_item.Checked = (menu_item Is checked_item)
    Next
End Sub

    Private Sub mnuEnglish_Click(sender As System.Object, e As EventArgs) _
    Handles mnuEnglish.Click, mnuFrench.Click, mnuDutch.Click, _ 
    mnuGerman.Click,mnuCroatian.Click, mnuCzech.Click, mnuHungarian.Click, _
    mnuIndonesian.Click, mnuItalian.Click, mnuPolish.Click, mnuSlovak.Click, _
    mnuSpanish.Click, mnuSwedish.Click, mnuTurkish.Click, mnuVietnamese.Click

    Dim item As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
    CheckMenuItem(mnuLanguage, item)

    Select Case item.Name
        Case "mnuEnglish"
            MsgBox("english")
        Case "mnuFrench"
            MsgBox("French")
        Case Else
            MsgBox("Other Languages")
    End Select
    End Sub
\$\endgroup\$
5
\$\begingroup\$

See this Stack Overflow answer, where Cody Gray explains the syntax for the two ways of registering event handlers in :

The first involves the use of the Handles keyword, which you append to the end of the event handler method's definition. [...] The second involves the explicit use of the AddHandler statement, just like += in C#.

This means instead of statically declaring all the handled events with a Handles keyword, you write code to add the handlers yourself:

Public Sub New()

    InitializeComponents()

    AddHandler mnuEnglish.Click, AdressOf mnuEnglish_Click
    AddHandler mnuFrench.Click, AdressOf mnuEnglish_Click
    '...

End Sub

Or even better, loop through the menu items in that menu object, and assing all Click events the AdressOf mnuEnglish_Click, so you won't have the opportunity to forget updating that piece of code when you add a new language / menu item in the designer:

Public Sub New()

    InitializeComponents()

    ForEach item As ToolStripMenuItem In mnu.DropDownItems.OfType(Of ToolStripMenuItem)()
        AddHandler item.Click, AdressOf mnuEnglish_Click
    Next

End Sub
\$\endgroup\$
  • 1
    \$\begingroup\$ thanks to this, works great, still you need to check for type for ToolStripSeparator...the code you provided will have an error if there is a separator in DropDownItems in menus \$\endgroup\$ – mercenary Apr 27 '14 at 15:55
  • \$\begingroup\$ @mercenary interesting.. I would have thought item would be Nothing when it's a ToolStripSeparator, because of As ToolStripMenuItem - looks like you need to further filter the items with .OfType(Of ToolStripMenuItem)... I'll edit out the last part of my answer then ;) \$\endgroup\$ – Mathieu Guindon Apr 27 '14 at 19:31
3
\$\begingroup\$

The ToolStripItem contains a property called Tag which is used to store extra information about a menu item. This is where you could store information about the language. Then your event could be generalized by using the information in Tag.

mnuEnglish.Tag = "English" ' Instead of just a string, I would have a language class
mnuFrench.Tag = "French"
...

Private Sub mnuEnglish_Click(...

Dim item As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
    CheckMenuItem(mnuLanguage, item)

    MsgBox(item.Tag)

End Sub
\$\endgroup\$
1
\$\begingroup\$

so silly of me, simple google solve my problem

For Each item As ToolStripMenuItem In mnuLanguage.DropDownItems.OfType(Of ToolStripMenuItem)()
        If item.Name IsNot "mnuEnglish" Then
            AddHandler item.Click, AddressOf mnuEnglish_Click
        End If
Next

of this converted to LINQ expression thanks to Resharper

For Each item As ToolStripMenuItem In From mnu_items In mnuLanguage.DropDownItems.OfType(Of ToolStripMenuItem)() Where mnu_items.Name IsNot "mnuEnglish"
        AddHandler item.Click, AddressOf mnuEnglish_Click
Next
\$\endgroup\$
  • 1
    \$\begingroup\$ Could you explain what the difference between these is and how it improves things? It's not much of a review when it doesn't teach better practices. \$\endgroup\$ – SuperBiasedMan Sep 29 '15 at 19:35
1
\$\begingroup\$

Make sure you have only one handler for every event. If you use the "Handles" syntax at the end of the subroutine declaration for the click handler, that registers a handler.

For derived classes, if the base handler is defined with a "Handles" clause, it register a handler. If the overrides handler in the derived class is also defined with a "Handles" clause, it will register a second handler, and both will be triggered when the event is fired.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.