如何在C#控制台应用中通过委托实现动态菜单项
解决方案:用委托实现C#控制台菜单的动态标签更新
核心问题是原代码中MenuLabel是静态字符串,初始化时就固定了值,不会随game.Players.Count的变化自动更新。我们需要将标签改为动态计算的委托,让菜单每次绘制时都获取最新值。
步骤1:修改Menuitem类,支持动态标签
将原有的静态字符串属性替换为Func<string>类型的委托,让标签可以实时计算:
public class Menuitem { public string Shortcut { get; set; } = default!; // 动态标签委托:每次调用返回最新文本 public Func<string> LabelProvider { get; set; } = () => string.Empty; public Func<string?>? MethodToRun { get; set; } = null; public Func<string?>? SubMethodToRun { get; set; } = null; }
如果需要兼容原有静态标签的写法,可以保留MenuLabel属性并关联委托(可选):
public class Menuitem { public string Shortcut { get; set; } = default!; private string? _staticLabel; // 兼容静态标签设置 public string? MenuLabel { get => _staticLabel; set { _staticLabel = value; LabelProvider = () => value ?? string.Empty; } } // 动态标签委托,优先级高于静态标签 public Func<string> LabelProvider { get; set; } = () => string.Empty; public Func<string?>? MethodToRun { get; set; } = null; public Func<string?>? SubMethodToRun { get; set; } = null; }
步骤2:修改Menu类的Draw方法,使用动态标签
在绘制菜单时,调用LabelProvider委托获取最新文本,替代原来的静态字符串读取:
private void Draw() { if (!string.IsNullOrWhiteSpace(Title)) { Console.WriteLine(Title); Console.WriteLine(separatorstring); } foreach (var menuItem in MenuItems) { Console.Write(menuItem.Key); Console.Write(") "); // 调用委托获取实时标签 Console.WriteLine(menuItem.Value.LabelProvider()); } Console.WriteLine("b) Back"); Console.WriteLine("x) exit"); Console.WriteLine(separatorstring); Console.Write("Your choice:"); }
步骤3:初始化菜单时配置动态标签
针对玩家数量的菜单项,用Lambda表达式作为LabelProvider,每次执行都会读取最新的game.Players.Count:
var game = new GameEngine(2); // 默认2名玩家 var startNewGameMenu = new Menu("New Game", new List<Menuitem>() { new Menuitem() { Shortcut = "c", // 动态生成标签:每次绘制时获取当前玩家数 LabelProvider = () => $"Player count: {game.Players.Count}", MethodToRun = game.SetPlayersCount, }, new Menuitem() { Shortcut = "t", // 静态标签用Lambda包裹 LabelProvider = () => "Player names and types", }, new Menuitem() { Shortcut = "s", LabelProvider = () => "Start the game", MethodToRun = null }, });
如果用了兼容静态标签的Menuitem类,原有静态标签可以继续通过MenuLabel属性设置,不影响逻辑。
步骤4:优化SetPlayersCount方法(可选)
增加输入验证,避免非数字输入导致程序崩溃:
public string? SetPlayersCount() { Console.WriteLine("How many players?"); if (!int.TryParse(Console.ReadLine()?.Trim(), out int playerCount) || playerCount < 1) { Console.WriteLine("Invalid input! Please enter a positive number."); return null; } Players = new List<Player>(); for (int i = 0; i < playerCount; i++) { Players.Add(new Player()); } Console.WriteLine($"New amount of players is: {Players.Count}"); return $"New amount of players is: {Players.Count}"; }
效果验证
当用户选择快捷键c修改玩家数量后,回到菜单时,Draw方法会自动调用LabelProvider获取最新玩家数并显示,实现菜单文本的动态更新。
内容的提问来源于stack exchange,提问作者Renx71
相关产品推荐
相关产品推荐

