locked
Contextmenu, Determine calling control RRS feed

  • Question

  • I have a contextmenu, that has several sub menus the user will be able to select from. The problem is, I have several controls (Datagridview) that I need to know which one the user clicked on..

    So, when the user right clicks on Datagridview1 and the contextmenu comes up and the user select a submenu item, in that handle event, how do I determine with datagridview from Datagridview1, or Datagridview2 or Datagridview3?

    Friday, March 11, 2016 4:12 AM

Answers

  • Here is an example where ContextMenu1 is set to DataGridView1, DataGridView2 and ComboBox1.

    In ContextMenu opening event I change the caption/text of the first menu item dependent on the SourceControl.Name then in the click event for this menu item DataGridView1 parse the menu text which will contain "Column N" where N is the current column name, remove "Column " then present the value for the current cell. DataGridView2 I simply  have the caption/text to be DataGridView2 then in the event to react get the current cell value. ComboBox we check to see if an item is selected, if so show the item text.

    ''' <summary>
    ''' Change first menu item's caption depending on
    ''' who the control which invoked this event.
    ''' 
    ''' I handle the two DataGridView's differently,
    ''' see code on click event for the first menu item in
    ''' the case else for DataGridView1 vs a case for DataGridView2
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub ContextMenuStrip1_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
        If ContextMenuStrip1.SourceControl IsNot Nothing Then
            Select Case ContextMenuStrip1.SourceControl.Name
                Case "DataGridView1"
                    If DataGridView1.CurrentCell IsNot Nothing Then
                        Item1ToolStripMenuItem.Text = "Column " & DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex).Name
                    End If
                Case "DataGridView2"
                    Dim dg = DirectCast(ContextMenuStrip1.SourceControl, DataGridView)
                    If dg.CurrentCell IsNot Nothing Then
                        Item1ToolStripMenuItem.Text = "DataGridView2"
                    End If
                Case "ComboBox1"
                    Dim dg = DirectCast(ContextMenuStrip1.SourceControl, ComboBox)
                    Item1ToolStripMenuItem.Text = "Selected item value"
                Case Else
                    Item1ToolStripMenuItem.Text = "None"
            End Select
        End If
    End Sub
    ''' <summary>
    ''' Figure out via the menu caption/text who to work with
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Item1ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles Item1ToolStripMenuItem.Click
        Select Case Item1ToolStripMenuItem.Text
            Case "Selected item value"
                If ComboBox1.SelectedIndex = -1 Then
                    MessageBox.Show("Nothing selected")
                Else
                    MessageBox.Show(ComboBox1.Text)
                End If
    
            Case "DataGridView2"
                Dim dgv As DataGridView = CType(Me.Controls.Find(Item1ToolStripMenuItem.Text, False)(0), DataGridView)
                MessageBox.Show(dgv.CurrentCell.Value.ToString)
            Case Else
                If Item1ToolStripMenuItem.Text.StartsWith("Column") Then
                    Dim columName As String = Item1ToolStripMenuItem.Text.Replace("Column ", "")
                    Dim dgv As DataGridView = CType(Me.Controls.Find("DataGridView1", False)(0), DataGridView)
                    MessageBox.Show(dgv.CurrentRow.Cells(columName).Value.ToString)
                Else
                    MessageBox.Show("Not in case statment")
                End If
    
        End Select
    End Sub


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by LandLord324 Sunday, March 13, 2016 1:15 AM
    Friday, March 11, 2016 2:59 PM

All replies

  • So, when the user right clicks on Datagridview1 and the contextmenu comes up and the user select a submenu item, in that handle event, how do I determine with datagridview from Datagridview1, or Datagridview2 or Datagridview3?

    Record the 'sender' parameter that is available in the datagridview event handler for the right-click event.  For instance, save the datagridview to a variable, or save the name to a string, or whatever it is that you need to know about it.

    Then use this variable in the menu item click event handler to identify the datagridview.

    Friday, March 11, 2016 4:44 AM
  • Here is an example where ContextMenu1 is set to DataGridView1, DataGridView2 and ComboBox1.

    In ContextMenu opening event I change the caption/text of the first menu item dependent on the SourceControl.Name then in the click event for this menu item DataGridView1 parse the menu text which will contain "Column N" where N is the current column name, remove "Column " then present the value for the current cell. DataGridView2 I simply  have the caption/text to be DataGridView2 then in the event to react get the current cell value. ComboBox we check to see if an item is selected, if so show the item text.

    ''' <summary>
    ''' Change first menu item's caption depending on
    ''' who the control which invoked this event.
    ''' 
    ''' I handle the two DataGridView's differently,
    ''' see code on click event for the first menu item in
    ''' the case else for DataGridView1 vs a case for DataGridView2
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub ContextMenuStrip1_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
        If ContextMenuStrip1.SourceControl IsNot Nothing Then
            Select Case ContextMenuStrip1.SourceControl.Name
                Case "DataGridView1"
                    If DataGridView1.CurrentCell IsNot Nothing Then
                        Item1ToolStripMenuItem.Text = "Column " & DataGridView1.Columns(DataGridView1.CurrentCell.ColumnIndex).Name
                    End If
                Case "DataGridView2"
                    Dim dg = DirectCast(ContextMenuStrip1.SourceControl, DataGridView)
                    If dg.CurrentCell IsNot Nothing Then
                        Item1ToolStripMenuItem.Text = "DataGridView2"
                    End If
                Case "ComboBox1"
                    Dim dg = DirectCast(ContextMenuStrip1.SourceControl, ComboBox)
                    Item1ToolStripMenuItem.Text = "Selected item value"
                Case Else
                    Item1ToolStripMenuItem.Text = "None"
            End Select
        End If
    End Sub
    ''' <summary>
    ''' Figure out via the menu caption/text who to work with
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub Item1ToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles Item1ToolStripMenuItem.Click
        Select Case Item1ToolStripMenuItem.Text
            Case "Selected item value"
                If ComboBox1.SelectedIndex = -1 Then
                    MessageBox.Show("Nothing selected")
                Else
                    MessageBox.Show(ComboBox1.Text)
                End If
    
            Case "DataGridView2"
                Dim dgv As DataGridView = CType(Me.Controls.Find(Item1ToolStripMenuItem.Text, False)(0), DataGridView)
                MessageBox.Show(dgv.CurrentCell.Value.ToString)
            Case Else
                If Item1ToolStripMenuItem.Text.StartsWith("Column") Then
                    Dim columName As String = Item1ToolStripMenuItem.Text.Replace("Column ", "")
                    Dim dgv As DataGridView = CType(Me.Controls.Find("DataGridView1", False)(0), DataGridView)
                    MessageBox.Show(dgv.CurrentRow.Cells(columName).Value.ToString)
                Else
                    MessageBox.Show("Not in case statment")
                End If
    
        End Select
    End Sub


    Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.
    VB Forums - moderator
    profile for Karen Payne on Stack Exchange, a network of free, community-driven Q&A sites

    • Marked as answer by LandLord324 Sunday, March 13, 2016 1:15 AM
    Friday, March 11, 2016 2:59 PM
  • Another option, which I personally prefer, is to setup the context menu in code.  You can then use a lambda to define the menu item's click event handler.  This makes it really easy to refer to in-scope values, such as the DataGridView instance that you started with.

    Here's a little example:

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim setupContextMenu = Sub(target As DataGridView)
                                   target.ContextMenuStrip = New ContextMenuStrip()
                                   With target.ContextMenuStrip.Items
                                       .Add("Action One", Nothing, Sub(_sender As Object, _e As EventArgs)
                                                                       DoActionOne(target)
                                                                   End Sub)
                                       .Add("Action Two", Nothing, Sub(_sender As Object, _e As EventArgs)
                                                                       DoActionTwo(target)
                                                                   End Sub)
                                   End With
                               End Sub
        setupContextMenu(DataGridView1)
        setupContextMenu(DataGridView2)
        setupContextMenu(DataGridView3)
    End Sub
    
    Private Sub DoActionOne(target As DataGridView)
        MessageBox.Show($"{target.Name} Action 1")
    End Sub
    Private Sub DoActionTwo(target As DataGridView)
        MessageBox.Show($"{target.Name} Action 2")
    End Sub
    


    Reed Kimble - "When you do things right, people won't be sure you've done anything at all"

    Saturday, March 12, 2016 7:15 AM
  • thanks, I've not tried yours yet, but looks interesting, I will try it

    Sunday, March 13, 2016 1:16 AM