Easy C♯ Menus
I have written some easy to use C♯ menus, and I thought that I would post about them here.
There are currently 2 different methods (and 2 extra helper methods). Both methods also centre the dialog box in the middle of the console, and also don't produce much mess that needs cleaning up afterwards.
Firstly, here are the two helper methods:
//from https://stackoverflow.com/questions/17590528/pad-left-pad-right-pad-center-string
///<summary>
///Cool function from stackoverflow that pads a string on both sides to make it a given legnth.
///</summary>
///<param name="source">The source string to pad.</param>
///<param name="length">The desired length.</param>
///<returns>The padded string.</returns>
static string PadBoth(string source, int length)
{
int spaces = length - source.Length;
int padLeft = spaces/2 + source.Length;
return source.PadLeft(padLeft).PadRight(length);
}
//utility function that uses the above to pad a string to the current width of the console.
static string PadToWindowWidth(string str)
{
return PadBoth(str, Console.WindowWidth - 1);
}
These need to be included in addition to either (or both!) of the methods described below.
The first one is a flexible multiple choice selection window. You can pass in an array of string sthat you want the user to choose from, and the method will deal with the rest, returning the index in the array of the item that the user chose.
This method comes with support for an optional prompt to display at the top of the dialog box. If you omit it, the prompt will not be displayed.
Source code:
///<summary>
///Displays a nice multiple choice menu that the user can intract with using the arrow keys.
///</summary>
///<param name="options">An array of strings that should be used as the possible options in the menu.</param>
///<returns>The index of the option the user chose.</returns>
static int DisplayMenu(string[] options, string prompt = "")
{
int cursorstartx = Console.CursorLeft,
cursorstarty = Console.CursorTop,
menuWidth = (int)(Console.WindowWidth * 0.8),
menuHeight = 2 + (options.Length * 2) + 1;
if(prompt.Length > 0)
menuHeight += 2;
int currentIndex = 0;
string menu = "";
while(true)
{
Console.SetCursorPosition(cursorstartx, cursorstarty);
menu = "";
menu += new String('\n', ((Console.WindowHeight - 1) - menuHeight) / 2);
menu += PadToWindowWidth("".PadLeft(menuWidth, '-')) + "\n";
if(prompt.Length > 0)
{
menu += PadToWindowWidth("| " + PadBoth(prompt, menuWidth - 4) + " |") + "\n";
menu += PadToWindowWidth("".PadLeft(menuWidth, '-')) + "\n";
}
menu += PadToWindowWidth("|" + "".PadLeft(menuWidth - 2) + "|") + "\n";
for(int i = 0; i < options.Length; i++)
{
if(currentIndex == i)
{
menu += PadToWindowWidth("|" + PadBoth("> " + options[i] + " <", menuWidth - 2) + "|") + "\n";
}
else
{
menu += PadToWindowWidth("|" + PadBoth(options[i], menuWidth - 2) + "|") + "\n";
}
menu += PadToWindowWidth("|" + "".PadLeft(menuWidth - 2) + "|") + "\n";
}
menu += PadToWindowWidth("".PadLeft(menuWidth, '-'));
menu += new String('\n', ((Console.WindowHeight - 1) - menuHeight) / 2);
Console.WriteLine(menu);
ConsoleKeyInfo nextkey = Console.ReadKey(true);
switch(nextkey.Key.ToString())
{
case "UpArrow":
currentIndex--;
break;
case "DownArrow":
currentIndex++;
break;
case "Enter":
return currentIndex;
}
if(currentIndex < 0)
currentIndex = options.Length - 1;
if(currentIndex > options.Length - 1)
currentIndex = 0;
}
}
Confirm Dialog
In case you want to obtain an answer to a simple yes/no question, this second method allows you to ask the user to choose between 2 choices. Simply specify a prompt, and optionally the text to display in the place of the "Yes" / "No", and the method will return true or false, depending on which one the user selected.
Source code:
///<summary>
///Asks the user a simple yes/no question in the form of a console based dialog box.
///</summary>
///<param name="prompt">The question to ask the user.</param>
///<param name="trueText">The text to display in the place of "Yes"</param>
///<param name="falseText">The text to display in the place of "No"</param>
///<returns>True if the user selected "Yes", or false if the user selected "No".</returns>
static bool DisplayConfirm(string prompt, string trueText = "Yes", string falseText = "No")
{
int cursorstartx = Console.CursorLeft,
cursorstarty = Console.CursorTop,
menuWidth = (int)(Console.WindowWidth * 0.8),
menuHeight = 7,
currentIndex = 1;
string menu = "";
while(true)
{
Console.SetCursorPosition(cursorstartx, cursorstarty);
menu = "";
menu += new String('\n', ((Console.WindowHeight - 1) - menuHeight) / 2); //vertical centring
menu += PadToWindowWidth("".PadLeft(menuWidth, '-')) + "\n"; //dashes
menu += PadToWindowWidth("|" + "".PadLeft(menuWidth - 2) + "|") + "\n"; //space
menu += PadToWindowWidth("|" + PadBoth(prompt, menuWidth - 2) + "|") + "\n"; //prompt
menu += PadToWindowWidth("|" + "".PadLeft(menuWidth - 2) + "|") + "\n"; //space
menu += PadToWindowWidth("".PadLeft(menuWidth, '-')) + "\n"; //dashes
if(currentIndex == 0)
menu += PadToWindowWidth("|" + PadBoth(trueText, (menuWidth - 3) / 2) + "|" + PadBoth("> " + falseText + " <", (menuWidth - 3) / 2) + "|") + "\n";
else
menu += PadToWindowWidth("|" + PadBoth("> " + trueText + " <", (menuWidth - 3) / 2) + "|" + PadBoth(falseText, (menuWidth - 3) / 2) + "|") + "\n";
menu += PadToWindowWidth("".PadLeft(menuWidth, '-')) + "\n"; //dashes
menu += new String('\n', ((Console.WindowHeight - 1) - menuHeight) / 2); //vertical centring
Console.WriteLine(menu);
ConsoleKeyInfo nextkey = Console.ReadKey(true);
switch(nextkey.Key.ToString())
{
case "LeftArrow":
case "UpArrow":
currentIndex--;
break;
case "RightArrow":
case "DownArrow":
currentIndex++;
break;
case "Enter":
if(currentIndex == 0)
return true;
else
return false;
}
if(currentIndex < 0)
currentIndex = 1;
if(currentIndex > 1)
currentIndex = 0;
}
}
I will probably write a few more of these in the future, and make these current ones better.
Demonstration binaries are available upon request, simply leave a comment below.