You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:47:32