我正在尝试为C#.NET控制台应用程序编写一个简单的箭头驱动选项菜单。给定字符返回类型的选项字典,用户可以选择带有向上/向下键的选项,并使用Enter选择它。
问题是,switch语句在第一次运行后完全中断了程序。我试过放置断点并搞清楚,但没有用 -
编辑:决定将这些代码与一些同样写入该类的异步代码分开。无论出于何种原因,这让它按预期工作,所以..现在我需要弄清楚为什么异步会搞乱这个,没有等待像这样的同步操作。
码:
static char GetUserInput(Dictionary<char, String> options, int indent = 1) {
int optionAreaTop = Console.CursorTop;
Console.ForegroundColor = ConsoleColor.Yellow;
// First option, makes sure it's set in yellow
bool fo = true;
foreach (String opt in options.Values) {
Console.WriteLine(opt.PadLeft(indent + opt.Length, '\t'));
if (fo) { Console.ForegroundColor = ConsoleColor.White; fo = false; }
}
return DoMenu(options, optionAreaTop);
}
static char DoMenu(Dictionary<char, String> options, int optionAreaTop = 0) {
int answerIndex = 0;
int currentAnswerTop = optionAreaTop;
int indent = 2;
while (true) {
ConsoleKeyInfo kin = Console.ReadKey(true);
ConsoleKey ki = kin.Key;
switch (ki) {
case ConsoleKey.UpArrow:
if (currentAnswerTop - 1 >= optionAreaTop) {
// Rewrite selection in white
WriteOptionLine(currentAnswerTop, indent, options.Values.ElementAt(answerIndex), ConsoleColor.White);
WriteOptionLine(currentAnswerTop - 1, indent, options.Values.ElementAt(answerIndex - 1), ConsoleColor.Yellow);
currentAnswerTop -= 1;
answerIndex -= 1;
}
break;
case ConsoleKey.DownArrow:
if (answerIndex + 1 < options.Count - 1) {
// Rewrite selection in white
WriteOptionLine(currentAnswerTop, indent, options.Values.ElementAt(answerIndex), ConsoleColor.White);
WriteOptionLine(currentAnswerTop + 1, indent, options.Values.ElementAt(answerIndex + 1), ConsoleColor.Yellow);
currentAnswerTop += 1;
answerIndex += 1;
}
break;
case ConsoleKey.Enter:
return options.Keys.ElementAt(answerIndex);
default:
// Retry
break;
}
}
}
static void WriteOptionLine(int position, int indent, String option, ConsoleColor color) {
Console.SetCursorPosition(0, position);
Console.ForegroundColor = color;
Console.WriteLine(option.PadLeft(indent + option.Length, '\t'));
}
用法:
Dictionary<char, String> opts = new Dictionary<char, string>();
opts.Add('r', "[R]etry the Download");
opts.Add('m', "[M]anually add the file");
opts.Add('s', "[S]kip the file");
// GET_USER_INPUT
char choice = GetUserInput(opts, 2);
// DO WHATEVER
你的代码没有问题,除了一个,因为我已经在我的控制台应用程序中测试了,因为if
中你的ArrowDown
条件所以永远不能选择最后一个选项所以它会改变如下:
case ConsoleKey.DownArrow:
if (answerIndex + 1 <= options.Count - 1)
{
// Rewrite selection in white
WriteOptionLine(currentAnswerTop, indent, options.Values.ElementAt(answerIndex), ConsoleColor.White);
WriteOptionLine(currentAnswerTop + 1, indent, options.Values.ElementAt(answerIndex + 1), ConsoleColor.Yellow);
currentAnswerTop += 1;
answerIndex += 1;
}
break;
if (answerIndex + 1 < options.Count - 1)
应该是if (answerIndex + 1 <= options.Count - 1)
很明显,按Enter键控制台应用程序将退出,因为您将从DoMenu
返回return options.Keys.ElementAt(answerIndex);
并选择choice
变量。