Dayan
Dayan

Reputation: 8031

VB.NET - Access menu event from another form, works only on form_load

I have two forms in my application, one form is to create new connections, the other is the main form which holds the menu that will carry the connection names.

enter image description here

When i create a new connection under frmNewConnection form and try to click on the menu item that's generated, it wont display the Test message like it does when i reopen the program.

In the main form i have the following public sub.

frmMain which is the main form

Public Sub Connect_SubMenuItem_Click(ByVal sender As Object, ByVal e As EventArgs)
  Messagebox.Show("Test")
End Sub

That code never gets executed unless i restart my application then it works fine when i click on the newly generated menu item. But if i was to load the application and click on the "New Connection" Menu item and create the new connection then try to click it under the "Connections" menu then nothing happens, i don't get the "Test" Message box.

I have the following code under the frmNewConnection Accept button, which saves the name of the connection to the "Connections" menu.

frmMain.menuConnections.DropDownItems.Add(ConnectionName, Nothing, AddressOf frmMain.Connect_SubMenuItem_Click) ' save to menu

I also have a version of that code that executes on frmMain_load():

menuConnections.DropDownItems.Add(finalData(1).ToString, Nothing, AddressOf Connect_SubMenuItem_Click) ' save to menu

My Question here is, why won't the Test message appear when a new menu item is generated while in the program but it does show when i close the program and i re-open it..

Upvotes: 0

Views: 1847

Answers (2)

Decker97
Decker97

Reputation: 1653

You need to add the handler for the menu item after you add it to the menu:

Private Sub btnAddMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddMenuItem.Click
    Dim tsmi As New ToolStripMenuItem("Test")
    Me.MenuStrip1.Items.Add(tsmi)
    AddHandler tsmi.Click, AddressOf Me.TestMenu
End Sub

Private Sub TestMenu(ByVal Sender As Object, ByVal e As System.EventArgs)
    MessageBox.Show("Test Menu")
End Sub

Upvotes: 0

tcarvin
tcarvin

Reputation: 10855

If you are modifying the controls of one form from another form then you are probably going about the whole thing wrong.

First thing you need to do is take control of your program startup. VB hides this sometimes. This will allow you to capture your form variable. Then, consider refactoring a bit.

Some VB.NET psuedo-code (I apologize for any C# that leaks in here):

Class Program

   Private _appCtx As AppContext

   Sub Main()

      _appCtx = New AppContext()

      'perform whatever bootstrap logic you needed here, typically
      ' configuring and installing behaviors into the app context
      '
      '

      ' one single instace of your main form
      _appCtx.RootForm = New frmMain(); 'or better still, pass AppContext into the ctor 

      Application.Run(_appCtx.RootForm)

   End Sub

   'if you want to cheat a bit, include this getter to provide access to everyone
   'otherwise, pass the app context to those classes that require it
   Public Shared AppCtx() As AppContext
      Get
         return _appCtx
      End Get
   End Property


End Class

Public Class AppContext

   Public Property RootForm As Form

   Public Property Connections As Connections

   'other application-wide subsystems or data

End Class

Public Class Connections

   Public Event Changed As EventHandler

   Public Property Count As Integer

   'other properties including a getter for the child connection objects...

   Public Sub Add(newConn As Connection)
      'add to internal list then...
      If Changed IsNot Nothing Then
         Changed(this, EventArgs.Empty)
      End If
   End Sub

End Class

Public Class frmMain


   Sub Form_Load() 

      AddHandler AppCtx.Connections.Changed AddressOf(Connections_Changed)

   End Sub

   Sub Connections_Changed()
      'iterate the connections and refresh the menu
      'the menu gets refreshed without breaking encapsulation!
   End Sub

End Class

Public Class frmNewConnection 


   private sub Accept_Click()

      'do stuff to create a connection object

      'add to the current set of connections, this will broadcast to anyone who needs to know      
      AppCtx.Connection.Add(newConn)

   End Sub 

End Class

If you don't want to use the domain-object events for updates that is up to you, but the first part of the sample shows how to capture the startup form into a variable that you can then use in your program code.

Upvotes: 1

Related Questions