Results 1 to 1 of 1

Thread: Console Application - Menu

  1. #1

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,803

    Console Application - Menu

    I had a situation where I needed to provide users with a list of values and they had to select one. At first, I just had it loop over every item and prefix it with it's ordinal index. This worked, but I wanted to provide a more interactive way for the user to select an option, so I decided to whip something up that will allow the user to use their arrow keys to cycle through the items and select an option.

    This is the code:
    Code:
    Private Function GetSelectedMenu(menuItems As IEnumerable(Of String), Optional selectedIndex As Integer = 0) As Integer
        If (Not menuItems.Any()) Then
            Throw New ArgumentOutOfRangeException(NameOf(menuItems))
        End If
        If (selectedIndex < 0 OrElse selectedIndex > menuItems.Count - 1) Then
            Throw New ArgumentOutOfRangeException(NameOf(selectedIndex))
        End If
    
        Console.Clear()
        DisplayMenu(menuItems, selectedIndex)
    
        Dim key = Console.ReadKey()
        Select Case key.Key
            Case ConsoleKey.UpArrow
                If selectedIndex > 0 Then
                    selectedIndex -= 1
                End If
            Case ConsoleKey.DownArrow
                If (selectedIndex < menuItems.Count - 1) Then
                    selectedIndex += 1
                End If
            Case ConsoleKey.Enter
                Return selectedIndex
        End Select
    
        Return GetSelectedMenu(menuItems, selectedIndex)
    End Function
    
    Private Sub DisplayMenu(menuItems As IEnumerable(Of String), selectedIndex As Integer)
        If (Not menuItems.Any()) Then
            Throw New ArgumentOutOfRangeException(NameOf(menuItems))
        End If
        If (selectedIndex < 0 OrElse selectedIndex > menuItems.Count - 1) Then
            Throw New ArgumentOutOfRangeException(NameOf(selectedIndex))
        End If
    
        For menuItemIndex = 0 To menuItems.Count - 1
            If menuItemIndex = selectedIndex Then
                Console.ForegroundColor = ConsoleColor.Green
            End If
    
            Dim menuItem = menuItems(menuItemIndex)
            Console.WriteLine(menuItem)
            Console.ResetColor()
        Next
    End Sub
    And this is the implementation:
    Code:
    Console.CursorVisible = False
    
    Dim menuItems = Enumerable.Range(1, 5).Select(Function(i) $"Menu {i}")
    Dim selectedMenuItem = GetSelectedMenu(menuItems)
    
    Console.Clear()
    Console.WriteLine("You selected {0}", selectedMenuItem)
    Console.ReadLine()
    The basic idea is that you essentially end up an in a recursive loop where it will do the following:
    1. Clear the console
    2. Loop over the menu items
      1. Print the currently iterated item
      2. If the currently iterated item is the currently "selected" item, change the forecolor to green
    3. Call ReadKey
      1. If the key is enter, then return the selected index value.
      2. Otherwise...
        1. If the key is the up arrow, try to decrement the selected index value
        2. If the key is the down arrow, try to increment the selected index value
        3. Regardless of the input, recursively call the method by returning the method's value


    Something that I didn't include that might be useful is a "title" argument to the GetSelectedMenu's event signature that will display text at the top of the console before all the menu items.
    Last edited by dday9; Feb 2nd, 2024 at 10:46 PM.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width