我在控制台中创建了一个带子菜单的菜单。一切正常,但我想知道是否不可能改进我的程序结构。为了简化它并使其更通用。
class MainClass
{
public static void Main(string[] args)
{
MainMenu();
}
public static void MainMenu()
{
Console.WriteLine("Main Menu");
Console.WriteLine("--------------------");
Console.WriteLine("[1] Show activities");
Console.WriteLine("[2] Show teachers");
Console.WriteLine("[3] Show students");
Console.WriteLine("[4] Exit the program");
Console.WriteLine("--------------------\n");
Console.WriteLine("Please select an option from 1-4\n");
string choice = Console.ReadLine();
int number;
bool result = Int32.TryParse(choice, out number);
if (result)
{
Console.Clear();
SubMenu(number);
}
else
{
Console.WriteLine("Incorrect choice");
}
}
public static void SubMenu(int mainMenuChoice)
{
switch (mainMenuChoice)
{
case 1:
Console.WriteLine("Activities");
Console.WriteLine("[1] Show all activities");
Console.WriteLine("[2] Find a activity by his code");
Console.WriteLine("[3] Return Main Menu");
Console.WriteLine("[4] Exit the program");
Console.WriteLine("--------------------\n");
Console.WriteLine("Please select an option from 1-4\n");
break;
case 2:
Console.WriteLine("Teachers");
Console.WriteLine("[1] Show all teachers");
Console.WriteLine("[2] Find a teacher by his matricule");
Console.WriteLine("[3] Return Main Menu");
Console.WriteLine("[4] Exit the program");
Console.WriteLine("--------------------\n");
Console.WriteLine("Please select an option from 1-4\n");
break;
case 3:
Console.WriteLine("Students");
Console.WriteLine("[1] Show all students");
Console.WriteLine("[2] Find a student by his matricule");
Console.WriteLine("[3] Return Main Menu");
Console.WriteLine("[4] Exit the program");
Console.WriteLine("--------------------\n");
Console.WriteLine("Please select an option from 1-4\n");
break;
case 4:
Environment.Exit(0);
break;
}
string choice = Console.ReadLine();
int number;
bool result = Int32.TryParse(choice, out number);
if (result)
{
Action(mainMenuChoice, number);
}
else
{
Console.WriteLine("Incorrect choice");
}
}
public static void Action(int menu, int choice)
{
switch (menu)
{
case 1:
switch (choice)
{
case 1:
// Do Stuff
break;
case 2:
// Do Stuff
break;
case 3:
Console.Clear();
MainMenu();
break;
case 4:
Environment.Exit(0);
break;
}
break;
case 2:
switch (choice)
{
case 1:
// Do Stuff
break;
case 2:
// Do Stuff
break;
case 3:
Console.Clear();
MainMenu();
break;
case 4:
Environment.Exit(0);
break;
}
break;
case 3:
switch (choice)
{
case 1:
// Do Stuff
break;
case 2:
// Do Stuff
break;
case 3:
Console.Clear();
MainMenu();
break;
case 4:
Environment.Exit(0);
break;
}
break;
}
}
}
目前如果我必须添加一个子菜单,我必须在MainMenu()函数中添加一行,我必须在SubMenu()函数中添加一个案例,并且在Action中有多个选项( )。 只有一个子菜单可以,但是如果我必须添加十几个子菜单,很快就会变得无法管理。 我应该经历一个或多个班级,但我在结构上迷失了。
答案 0 :(得分:1)
我迅速做了一些事情,以展示解决问题的方法。我评论了大部分代码,但询问是否有任何不清楚的地方。对我来说,主要的优点是你可以将菜单作为对象在一个地方声明。在我的代码中,我在Main方法中明确地完成了这个,但您可以轻松编写工厂方法来为您生成菜单。
class Program
{
//represents a line/option in a menu
class MenuItem
{
// displayed in the menu
public string Text { get; set; }
//is there a sub menu
public bool HasSubMenu { get; set; }
// if there's a submenu, what's its id
public int? SubMenuId { get; set; }
//if there isn't a sub menu, what should we do
public Action Action { get; set; }
}
//represents one menu i.e. a collection of options
class Menu
{
public Menu()
{
MenuItems = new List<MenuItem>();
}
public int MenuId { get; set; }
public List<MenuItem> MenuItems { get; set; }
public string Title { get; set; }
public void PrintToConsole()
{
foreach (MenuItem item in MenuItems)
{
Console.WriteLine(MenuItems.IndexOf(item) + " : " + item.Text);
}
}
}
//represents all the menus
class MenuCollection
{
public MenuCollection()
{
Menus = new List<Menu>();
}
public List<Menu> Menus { get; set; }
public void ShowMenu(int id)
{
//get the menu we want to display and call its PrintToConsole method
var currentMenu = Menus.Where(m => m.MenuId == id).Single();
currentMenu.PrintToConsole();
//wait for user input
string choice = Console.ReadLine();
int choiceIndex;
//once we have the users selection make sure its an integer and in range of our menu options
//if not then show an error message and re-display the menu
if (!int.TryParse(choice, out choiceIndex) || currentMenu.MenuItems.Count < choiceIndex || choiceIndex < 0)
{
Console.Clear();
Console.WriteLine("Invalid selection - try again");
ShowMenu(id);
}
else
{
// if the selection is good, then retrieve the corresponding menu item
var menuItemSelected = currentMenu.MenuItems[choiceIndex];
// if there's a sub menu then display it
if (menuItemSelected.HasSubMenu)
{
Console.Clear();
ShowMenu(menuItemSelected.SubMenuId.Value);
}
// otherwise perform whatever action we need
else
{
menuItemSelected.Action();
}
}
}
}
static void Main(string[] args)
{
// build a collection of menus
// can have as deep a structure as you like
// give each menu a unique integer MenuId
// link to other menus by setting HasSubMenu to true, and the SubMenuId to the MenuId of the menu you wish to link to
// or, set HasSubMenu to false, and have an Action performed when the menuitem is selected
MenuCollection collection = new MenuCollection()
{
Menus =
{
new Menu()
{
MenuId = 1,
MenuItems =
{
new MenuItem()
{
Text = "Go to sub menu",
HasSubMenu = true,
SubMenuId = 2
},
new MenuItem()
{
Text = "Print Action",
HasSubMenu = false,
Action = () =>
{
Console.WriteLine("I printed from an action");
}
}
}
},
new Menu()
{
MenuId = 2,
MenuItems =
{
new MenuItem()
{
Text = "Sub menu option 1",
HasSubMenu = false,
Action = () =>
{
Console.WriteLine("Printed from a sub menu");
}
},
new MenuItem()
{
Text = "Back to the top menu",
HasSubMenu = true,
SubMenuId = 1
}
}
}
}
};
collection.ShowMenu(1);
Console.ReadLine();
}
}
答案 1 :(得分:0)
我最近一直在制作许多小型CLI工具,我只是充实了活动,但这里是我通常喜欢采用大量分支菜单/逻辑的方法的一个例子:
class Program
{
static T GetChoice<T>(List<Tuple<string, T>> choices)
{
var i = 1;
choices.ForEach(x => Console.WriteLine($"[{i++}]: {x.Item1}"));
var choiceIndex = int.Parse(Console.ReadLine());
return choices[choiceIndex - 1].Item2;
}
static void Main(string[] args)
{
Console.WriteLine("Main Menu: ");
var choices = new List<Tuple<string, Action>>()
{
new Tuple<string, Action>("Show Activities", ShowActivities),
new Tuple<string, Action>("Show Teachers", ShowTeachers),
new Tuple<string, Action>("Show Students", ShowStudents),
new Tuple<string, Action>("Exit", Exit),
};
GetChoice(choices)();
}
static void ShowActivities()
{
Console.WriteLine("Activities: ");
var choices = new List<Tuple<string, Action>>()
{
new Tuple<string, Action>("Show all activities", ShowAllActivities),
new Tuple<string, Action>("Find activity by code", FindActivityByCode),
new Tuple<string, Action>("Return to main menu", () => { Main(null); }),
new Tuple<string, Action>("Exit the program", Exit),
};
GetChoice(choices)();
}
static void ShowTeachers()
{
Console.WriteLine("Teachers: ");
var choices = new List<Tuple<string, Action>>();
}
static void ShowStudents()
{
Console.WriteLine("Students: ");
var choices = new List<Tuple<string, Action>>();
}
static void ShowAllActivities()
{
//Do stuff
}
static void FindActivityByCode()
{
//Do stuff
}
static void ReturnToMainMenu()
{
//Do stuff
}
static void Exit()
{
Environment.Exit(0);
}
}