Home

Applications Menus: The Contextual Menu

 

Contextual Menus

 

Introduction

In our introduction to the main menu, we saw that, to access it, the user clicks one of its categories. A contextual menu is one that appears when the user right-clicks an area of an application or form. In most applications, when the user right-clicks a title bar, the operating system is configured to display a system menu. Here is an example:

Operating system's title bar menu

A menu is considered, or qualifies as, popup if, or because, it can appear anywhere on the form as the programmer wishes. Such a menu is also referred to as context-sensitive or contextual because its appearance and behavior depend on where it displays on the form or on a particular control. The person who creates the application decides if or where the contextual menu would appear. Because this characteristic is up to the programmer, the same application can display different types of popup menus depending on where the user right-clicks. Here are examples:

Context-sensitive menu

Contextual menu

The first difference between a main menu and a popup menu is that a popup menu appears as one category or one list of items and not like a group of categories of menus like a main menu. Secondly, while a main menu by default is positioned on the top section of a form, a popup menu doesn't have a specific location on the form.

Practical LearningPractical Learning: Creating a Menu

  1. Start Microsoft Visual Basic
  2. Create a new Windows Application named AltairRealtors3b
  3. In the Solution Explorer, right-click Form1.vb and click Rename
  4. Type AltairRealtors.vb and press Enter
  5. From the Menus & Toolbars section of the Toolbox, click the MenuStrip button MenuStrip and click the form
  6. While the menu strip is still selected, in the Properties window, click (Name), type MenuMain  and press Enter
  7. On the form, click Type Here, type File and press Enter
  8. On the form, click File.
    In the Properties window, click (Name) and type MenuFile
  9. On the form, click File and under it, click the Type Here box
  10. Type New Property and press Enter
  11. On the form, click File and click New Property.
    In the Properties window, click (Name) and type MenuFileNewProperty
  12. On the form, click File and, under New Property, click the Type Here box
  13. Type Exit and press Enter
  14. On the form, click File and click Exit.
    In the Properties window, click (Name) and type MenuFileExit
  15. Complete the design of the form as follows:
     
    Altair Realtors - Available Properties Listing
    Control Text Name Other Properties
    MenuStrip MenuStrip      
    Label Label Altair Realtors - Properties Listing   Font: Times New Roman, 21.75pt, style=Bold
    ForeColor: MediumBlue
    ListView ListView   lvwProperties  
    Columns (Name) Text TextAlign Width
    colPropertyNumber Prop #   50
    colPropertyType Property Type   78
    colAddress Address   130
    colCity City   80
    colState State   40
    colZIPCode ZIP Code Center 58
    colBedrooms Beds Right 40
    colBathrooms Baths Right 40
    colMarketValue Market Value Right 75
  16. On the main menu, click Project -> Add Windows Form...
  17. Set the Name to RealEstateProperty and click Add
  18. Design the form as follows:
     
    Altair Realtors
    Control Text Name Other Properties
    Label Label Property #:    
    TextBox TextBox   txtPropertyNumber Modifiers: Public
    Label Label Property Type:    
    ComboBox ComboBox   cbxPropertyTypes Modifiers: Public
    Items:
    Unknown
    Single Family
    Townhouse
    Condominium
    Label Label Address:    
    TextBox TextBox   txtAddress Modifiers: Public
    Label Label City:    
    TextBox TextBox   txtCity Modifiers: Public
    Label Label State:    
    ComboBox TextBox   cbxStates Modifiers: Public
    Items:
    DC
    MD
    PA
    VA
    WV
    Label Label ZIP Code:    
    TextBox TextBox   txtZIPCode Modifiers: Public
    Label Label Bedrooms:    
    TextBox TextBox 0 txtBedrooms Modifiers: Public
    Label Label Bathrooms:    
    TextBox TextBox 1.0 txtBathrooms Modifiers: Public
    Label Label Market Value:    
    TextBox TextBox 0.00 txtMarketValue Modifiers: Public
    Button Button OK btnOK DialogResult: OK
    Button Button Cancel btnCancel DialogResult: Cancel
    Form
    FormBorderStyle: FixedDialog
    Text: Altair Realtors - Available Property
    StartPosition: CenterScreen
    AcceptButton: btnOK
    CancelButton: btnCancel
    MaximizeBox: False
    MinimizeBox: False
    ShowInTaskBar: False
  19. Display the AltairRealtors form
  20. Right-click the form and click View Code
  21. In the Class Name combo box, select MenuFileNewProperty
  22. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub MenuFileNewProperty_Click(ByVal sender As Object, _
                                              ByVal e As System.EventArgs) _
                                              Handles MenuFileNewProperty.Click
            Dim rndNumber As Random
            Dim number1 As Integer
            Dim number2 As Integer
            Dim PropertyNumber As String
            Dim dlgProperty As RealEstateProperty
    
            rndNumber = New Random(DateTime.Now.Millisecond)
            number1 = rndNumber.Next(100, 999)
            number2 = rndNumber.Next(100, 999)
            PropertyNumber = number1 & number2
            dlgProperty = New RealEstateProperty
    
            dlgProperty.txtPropertyNumber.Text = PropertyNumber
            dlgProperty.Text = "Altair Realtors - New Property"
    
            If dlgProperty.ShowDialog() = Windows.Forms.DialogResult.OK Then
                Dim strPropertyType As String = dlgProperty.cbxPropertyTypes.Text
                Dim strAddress As String = dlgProperty.txtAddress.Text
                Dim strCity As String = dlgProperty.txtCity.Text
                Dim strState As String = dlgProperty.cbxStates.Text
                Dim strZIPCde As String = dlgProperty.txtZIPCode.Text
                Dim strBedrooms As String = dlgProperty.txtBedrooms.Text
                Dim strBathrooms As String = dlgProperty.txtBathrooms.Text
                Dim strMarketValue As String = dlgProperty.txtMarketValue.Text
    
                Dim lviProperty As ListViewItem = _
                    New ListViewItem(dlgProperty.txtPropertyNumber.Text)
    
                lviProperty.SubItems.Add(strPropertyType)
                lviProperty.SubItems.Add(strAddress)
                lviProperty.SubItems.Add(strCity)
                lviProperty.SubItems.Add(strState)
                lviProperty.SubItems.Add(strZIPCde)
                lviProperty.SubItems.Add(strBedrooms)
                lviProperty.SubItems.Add(strBathrooms)
                lviProperty.SubItems.Add(strMarketValue)
                lvwProperties.Items.Add(lviProperty)
            End If
    End Sub
  23. In the Class Name combo box, select MenuFileExit
  24. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub MenuFileExit_Click(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) _
                                       Handles MenuFileExit.Click
            End
    End Sub
  25. Execute the application
     
    Using a menu item at execution time
  26. To close the form, click File -> Exit

Creating a Contextual Menu

To support the creation and management of contextual menus, the .NET Framework provides the ContextMenuStrip class. This class is derived from ToolStripDropDownMenu, which itself is based on the ToolStripDropDown class. The ToolStripDropDown class is derived from ToolStrip.

To visually create a contextual menu, in the Menus & Toolbars section of the Toolbox, click the ContextMenuStrip button and click the form. Once you have a ContextMenuStrip object, you can create its menu items. To do this, as mentioned for the MenuStrip, you can click the first Type Here line, type a string, press Enter, and continue creating the other menu items in the same way.

Unlike a main menu, a popup menu provides a single list of items. If you want different popup menus for your form, you have two options. You can create various popup menus or programmatically change your single popup menu in response to something or some action on your form.

To programmatically create a contextual menu, start by declaring a handle to ContextMenuStrip. Here is an example:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Public Class Starter
        Inherits Form

        Private Contextual As ContextMenuStrip

        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()

            Contextual = New ContextMenuStrip

        End Sub

    End Class

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

To assist you with each item of a contextual menu, ToolStrip, the ancestor to the ContextMenuStrip class, is equipped with a property named Items. This property is of type ToolStripItemCollection, which is a collection-based class. The ToolStripItemCollection class implements the IList, the ICollection, and the IEnumerable interfaces.

To create one or more menu items, you can use the various techniques we reviewed for the main menu. Here are examples:

Imports System.Drawing
Imports System.Windows.Forms

Module Exercise

    Public Class Starter
        Inherits Form

        Private MenuEditCut As ToolStripMenuItem
        Private Contextual As ContextMenuStrip

        Dim components As System.ComponentModel.Container

        Public Sub New()
            InitializeComponent()
        End Sub

        Public Sub InitializeComponent()

            Contextual = New ContextMenuStrip
            MenuEditCut = New ToolStripMenuItem("Cut")

            Dim MenuEdit() As ToolStripMenuItem = _
            { _
                New ToolStripMenuItem("Copy"), _
                New ToolStripMenuItem("Paste") _
            }

        End Sub

    End Class

    Function Main() As Integer

        Dim frmStart As Starter = New Starter

        Application.Run(frmStart)

        Return 0
    End Function

End Module

After creating a menu item, to add it to the contextual menu, you can call the ToolStripItemCollection.Add() method. To add an array of items, you can call the create ToolStripItemCollection.AddRange() method. Here are examples:

Public Sub InitializeComponent()

            Contextual = New ContextMenuStrip
            MenuEditCut = New ToolStripMenuItem("Cut")

            Dim MenuEdit() As ToolStripMenuItem = _
            { _
                New ToolStripMenuItem("Copy"), _
                New ToolStripMenuItem("Paste") _
            }

            Contextual.Items.Add(MenuEditCut)
            Contextual.Items.AddRange(MenuEdit)

End Sub

Practical Learning Practical Learning: Introducing Contextual Menus

  1. From the Menus & Toolbars section of the Toolbox, click ContextMenuStrip and click the form
  2. While the context menu strip is still selected, in the Properties window click (Name) and type MenuWithProperties
  3. Then click Items and click its ellipsis button
  4. Under the Select Item And Add To List combo box, make sure MenuItem is selected and click Add
  5. On the right side, click Text and type Edit
  6. Click (Name) and type MenuEditProperty
  7. On the left side, click Add and, on the right side, change the properties as follows:
    Text: Delete
    (Name): MenuDeleteProperty
  8. On the left side, click Add and, on the right side, change the properties as follows:
    Text: Clear
    (Name): MenuClearProperties
     
    Items Collection Editor
  9. Click OK
  10. From the Menus & Toolbars section of the Toolbox, click ContextMenuStrip and click the form
  11. While the context menu strip is still selected, in the Properties window click (Name) and type MenuNoProperty
  12. On the form, under ContextMenuStrip, click Type Here
  13. Type New Property and press Enter
  14. On the form, under ContextMenuStrip, click New Property
  15. In the Properties window, click (Name), type MenuNewProperty and press Enter

Using a Contextual Menu

By default, a newly created contextual menu is attached neither to the form nor to any control on it. In order to display a context menu, you must assign its name to the control. To support this, Control, the ancestor to all visual controls of the .NET Framework, is equipped, and provides to its children, a property named ContextMenuStrip, which is of type ContextMenuStrip.

To visually assign a contextual menu to a control during design, click the control. In the Properties window, click the ContextMenuStrip field, then click the arrow of its combo box, and select the menu. If you had created more than one contextual menu, the combo box would show all of them and you can choose the one you want to use as default.

To programmatically specify the contextual menu of a control, assign a ContextMenuStrip object to its ContextMenuStrip property. Here is an example:

Public Sub InitializeComponent()

            Contextual = New ContextMenuStrip
            MenuEditCut = New ToolStripMenuItem("Cut")

            Dim MenuEdit() As ToolStripMenuItem = _
            { _
                New ToolStripMenuItem("Copy"), _
                New ToolStripMenuItem("Paste") _
            }

            Contextual.Items.Add(MenuEditCut)
            Contextual.Items.AddRange(MenuEdit)

            ContextMenuStrip = Contextual

End Sub

After assigning a ContextMenuStrip object to a control, when you right-click (actually when the user right-clicks) the control, the contextual menu would display. The above code would produce:

Contextual Menu

Practical LearningPractical Learning: Creating a Context Menu

  1. Right-click the form and click View Code
  2. Just under the Public Class AltairRealtors line, declare a ListViewItem variable named itmSelected
     
    Public Class AltairRealtors
    
        Private itmSelected As ListViewItem
    
    . . . No Change
    
    
  3. In the Class Name combo box, select (AltairRealtors Events)
  4. In the Method Name combo box, select Load and implement the event as follows:
     
    Private Sub AltairRealtors_Load(ByVal sender As Object, _
                                        ByVal e As System.EventArgs) _
                                        Handles Me.Load
            itmSelected = New ListViewItem()
            lvwProperties.ContextMenuStrip = MenuNoProperty
    End Sub
  5. In the Class Name combo box, select lvwProperties
  6. In the Method Name combo box, select MouseDown and implement the event as follows:
     
    Private Sub lvwProperties_MouseDown(ByVal sender As Object, _
                            ByVal e As System.Windows.Forms.MouseEventArgs) _
                                            Handles lvwProperties.MouseDown
            If e.Button = Windows.Forms.MouseButtons.Right Then
                If lvwProperties.SelectedItems.Count > 0 Then
                    itmSelected = lvwProperties.SelectedItems(0)
                Else
                    itmSelected = Nothing
                End If
            End If
    End Sub
  7. Save the file

Coding Contextual Menus

In your application, you can create as many contextual menus as you want. If you have different controls, each can have its own contextual menu or many can share a contextual menu. Also, you can use different contextual menus for a control and decide what menu to display when/why.

There is nothing particularly specific with writing code for a popup menu item. You approach it exactly as if you were dealing with a menu item of a main menu. You can write code for an item of a popup menu independent of any other item of a main menu. If you want an item of a popup menu to respond to the same request as an item of a main menu, you can write code for one of the menu items (either the item on the main menu or the item on the popup menu) and simply call its Click event in the event of the other menu item.

Practical LearningPractical Learning: Using Various Contextual Menus

  1. In the Class Name combo box, select lvwProperties
  2. In the Method Name combo box, select ItemSelectionChanged and implement the event as follows:
     
    Private Sub lvwProperties_MouseDown(ByVal sender As Object, _
                            ByVal e As System.Windows.Forms.MouseEventArgs) _
                                            Handles lvwProperties.MouseDown
            If e.Button = Windows.Forms.MouseButtons.Right Then
                If lvwProperties.SelectedItems.Count > 0 Then
                    itmSelected = lvwProperties.SelectedItems(0)
                Else
                    itmSelected = Nothing
                End If
            End If
    End Sub
  3. In the Class Name combo box, select MenuEditProperties
  4. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub MenuEditProperty_Click(ByVal sender As Object, _
                                           ByVal e As System.EventArgs) _
                                           Handles MenuEditProperty.Click
        ' Prepare to open the AvailableProperties dialog box
        Dim dlgProperty As RealEstateProperty = New RealEstateProperty
    
        ' Make sure an item, and only one, is selected
        If (lvwProperties.SelectedItems.Count = 0) Or _
            (lvwProperties.SelectedItems.Count > 1) Then
            Exit Sub
        End If
    
        ' Identify the item that is currently selected
        Dim lviCurrent As ListViewItem = lvwProperties.SelectedItems(0)
    
        ' Display the ItemDetails dialog box with the item number
        dlgProperty.txtPropertyNumber.Text = lviCurrent.Text
        dlgProperty.cbxPropertyTypes.Text = lviCurrent.SubItems(1).Text
        dlgProperty.txtAddress.Text = lviCurrent.SubItems(2).Text
        dlgProperty.txtCity.Text = lviCurrent.SubItems(3).Text
        dlgProperty.cbxStates.Text = lviCurrent.SubItems(4).Text
        dlgProperty.txtZIPCode.Text = lviCurrent.SubItems(5).Text
        dlgProperty.txtBedrooms.Text = lviCurrent.SubItems(6).Text
        dlgProperty.txtBathrooms.Text = lviCurrent.SubItems(7).Text
        dlgProperty.txtMarketValue.Text = lviCurrent.SubItems(8).Text
    
        If dlgProperty.ShowDialog() = Windows.Forms.DialogResult.OK Then
        lvwProperties.SelectedItems(0).Text = _
    		dlgProperty.txtPropertyNumber.Text
            lvwProperties.SelectedItems(0).SubItems(1).Text = _
    		dlgProperty.cbxPropertyTypes.Text
            lvwProperties.SelectedItems(0).SubItems(2).Text = _
    		dlgProperty.txtAddress.Text
            lvwProperties.SelectedItems(0).SubItems(3).Text = _
    		dlgProperty.txtCity.Text
            lvwProperties.SelectedItems(0).SubItems(4).Text = _
    		dlgProperty.cbxStates.Text
            lvwProperties.SelectedItems(0).SubItems(5).Text = _
    		dlgProperty.txtZIPCode.Text
            lvwProperties.SelectedItems(0).SubItems(6).Text = _
    		dlgProperty.txtBedrooms.Text
            lvwProperties.SelectedItems(0).SubItems(7).Text = _
    		dlgProperty.txtBathrooms.Text
            lvwProperties.SelectedItems(0).SubItems(8).Text = _
    		dlgProperty.txtMarketValue.Text
        End If
    End Sub
  5. In the Class Name combo box, select MenuDeleteProperty
  6. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub MenuDeleteProperty_Click(ByVal sender As Object, _
                                         ByVal e As System.EventArgs) _
                                         Handles MenuDeleteProperty.Click
            If lvwProperties.SelectedItems.Count = 0 Then Exit Sub
            Dim Answer As MsgBoxResult
    
            Answer = MsgBox("Are you sure you want " & _
                            "to delete that property?", _
                            MsgBoxStyle.YesNo Or MsgBoxStyle.Question, _
                            "Delete Property")
    
            If Answer = MsgBoxResult.Yes Then
                lvwProperties.SelectedItems(0).Remove()
            End If
    End Sub
  7. In the Class Name combo box, select MenuClearProperty
  8. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub MenuClearProperties_Click(ByVal sender As Object, _
                                          ByVal e As System.EventArgs) _
                                      Handles MenuClearProperties.Click
            Dim Answer As MsgBoxResult
            Answer = MsgBox("Are you sure you want " & _
                            "to delete all properties?", _
                        MsgBoxStyle.YesNo Or MsgBoxStyle.Question, _
                "Remove all Properties")
    
            If Answer = MsgBoxResult.Yes Then
                lvwProperties.Items.Clear()
            End If
    End Sub
  9. In the Class Name combo box, select MenuNewProperty
  10. In the Method Name combo box, select Click and implement the event as follows:
     
    Private Sub MenuNewProperty_Click(ByVal sender As Object, _
                                          ByVal e As System.EventArgs) _
                                          Handles MenuNewProperty.Click
            MenuFileNewProperty_Click(sender, e)
    End Sub
  11. Execute the application and test it
  12. Right-click an empty line of the list view to see the contextual menu and click New Property
     
    Context Menu
     
  13. Right-click the list view and click Edit
     
    Using context-sensitive help
     
  14. Right-click a row on the form and click Delete
  15. Accept to delete the property
  16. Close the form and return to your programming environment
 

Home Copyright © 2008-2016, FunctionX, Inc.