10分钟上手 Terminal.Gui:搭建终端任务管理面板

10 次阅读 0 点赞 0 评论 10 分钟原创技术教程

从零学习用 C# + Terminal.Gui 搭建交互式终端应用,涵盖窗口创建、相对布局、列表数据绑定与事件处理,可用于运维工具和 CLI 管理面板开发。

#C# #Terminal.Gui #TUI #终端UI #.NET #跨平台 #实战教程

10 分钟上手 Terminal.Gui:搭建终端任务管理面板

为什么需要终端 UI?

后端开发和运维工作中,经常需要编写巡检脚本或部署工具。传统的 Console.WriteLine + Console.ReadLine 组合能跑通功能,但交互体验欠佳:参数输错只能重来,查看历史状态需要滚动终端,实现菜单跳转得维护大量 switch-case

Terminal.Gui 是一个 .NET 跨平台终端 UI 工具包,能让终端应用拥有菜单、按钮、表格、输入框、进度条等交互组件。它不依赖图形界面,SSH 连接服务器后依然流畅运行。

这篇教程将带你从零搭建一个终端任务管理面板——支持查看任务列表、添加新任务、标记完成状态。完成后可直接复用到运维工具或 CLI 管理面板中。

前置条件

  • .NET 8+ SDK:终端执行 dotnet --version 能输出版本即可
  • 基础 C# 知识:会用 dotnet new 创建项目、能运行控制台程序就行
  • 无需前端经验,不依赖 Linux GUI 环境

第一步:项目初始化

创建控制台项目并安装 Terminal.Gui:

bash 复制代码
dotnet new console -n TaskManagerTUI -f net8.0
cd TaskManagerTUI
dotnet add package Terminal.Gui

Terminal.Gui v2 采用实例化的 IApplication 架构,手动从头搭建比使用项目模板更利于理解底层生命周期和后续排错。

第二步:验证环境——Hello World

Program.cs 中写入最基础的测试代码:

csharp 复制代码
using Terminal.Gui;
using Terminal.Gui.App;
using Terminal.Gui.Views;

using IApplication app = Application.Create();
app.Init();

using Window window = new() { Title = "Hello TUI" };

Label label = new()
{
    Text = "Terminal.Gui 跑起来了!按 Esc 关闭",
    X = Pos.Center(),
    Y = Pos.Center()
};
window.Add(label);

app.Run(window);

执行 dotnet run,终端会弹出居中显示的文字窗口,按 Esc 退出。

关键概念说明:

  • Application.Create() 取代了 v1 的静态类调用,v2 改为实例模式,方便多实例和测试
  • Pos.Center() 是布局系统核心——无需手动计算坐标,自动居中;Pos.Percent(50) 支持百分比定位
  • app.Run() 进入事件循环,阻塞主线程直到窗口关闭

第三步:搭建任务管理面板

3.1 定义数据模型

创建任务类:

csharp 复制代码
class TaskItem
{
    public string Name { get; set; } = "";
    public bool IsDone { get; set; }
    public override string ToString() => IsDone ? $"✓ {Name}" : $"○ {Name}";
}

覆盖 ToString() 很重要——Terminal.Gui 的列表控件直接使用该方法渲染显示文本。

3.2 完整交互面板代码

替换 Program.cs

csharp 复制代码
using Terminal.Gui;
using Terminal.Gui.App;
using Terminal.Gui.Views;

using IApplication app = Application.Create();
app.Init();

using Window window = new() { Title = "任务管理面板 (q 退出)" };

// 左侧任务列表
ListView taskList = new()
{
    X = 0,
    Y = Pos.Top(window),
    Width = Dim.Fill(20),
    Height = Dim.Fill(1),
    AllowsMarking = false
};

List<TaskItem> tasks = new()
{
    new TaskItem { Name = "部署线上服务" },
    new TaskItem { Name = "审查 PR #42" },
    new TaskItem { Name = "写周报" },
};
taskList.SetSource(new BindingList<TaskItem>(tasks));

// 右侧输入与按钮
TextField input = new()
{
    X = Pos.Right(taskList) + 1,
    Y = 1,
    Width = Dim.Fill(2),
    Text = ""
};

Button addBtn = new()
{
    Text = "添加",
    X = Pos.Right(taskList) + 1,
    Y = 3,
    Width = 10
};

Button doneBtn = new()
{
    Text = "标记完成",
    X = Pos.Right(taskList) + 1,
    Y = 5,
    Width = 10
};

Label statusLabel = new()
{
    Text = "就绪",
    X = Pos.Right(taskList) + 1,
    Y = Dim.Fill(2),
    Width = Dim.Fill(2)
};

// 事件绑定
addBtn.Accept += (s, e) =>
{
    if (!string.IsNullOrWhiteSpace(input.Text?.ToString()))
    {
        tasks.Add(new TaskItem { Name = input.Text?.ToString() ?? "" });
        taskList.SetSource(new BindingList<TaskItem>(tasks));
        input.Text = "";
        statusLabel.Text = $"已添加 {tasks.Count} 项";
    }
};

doneBtn.Accept += (s, e) =>
{
    if (taskList.SelectedItem >= 0 && taskList.SelectedItem < tasks.Count)
    {
        tasks[taskList.SelectedItem].IsDone = true;
        taskList.SetSource(new BindingList<TaskItem>(tasks));
        statusLabel.Text = "已标记完成";
    }
};

window.Add(taskList, input, addBtn, doneBtn, statusLabel);

// 快捷键退出
window.KeyPress += (s, e) =>
{
    if (e.KeyEvent.Key == (Key)113)
        app.RequestStop();
};

app.Run(window);

运行后左侧显示任务列表,右侧提供输入框和按钮。输入文本点击"添加"可追加条目,选中条目点击"标记完成"会在前方添加 ✓ 符号。

3.3 核心机制解析

  • ListView + BindingList:v2 推荐的列表数据源方案。BindingList 提供变更通知,SetSource 触发视图刷新
  • Dim.Fill()Pos.Right():相对定位系统避免硬编码坐标。Dim.Fill(20) 表示填满可用宽度并右侧预留 20 列,窗口缩放时自动适配
  • 事件驱动模型Accept 事件响应按钮点击(支持回车和鼠标),KeyPress 监听键盘事件,无需手动编写事件循环
  • 实例化架构:UI 元素使用 using 包装,v2 确保资源在作用域结束时正确释放

常见问题与避坑指南

终端显示乱码或框线断裂

确认终端支持 UTF-8 且字体包含 Unicode 框线字符。Linux 推荐 tmux + Nerd Font;Windows 使用最新版 Windows Terminal,避免老版 cmd.exe。

v1 旧代码迁移到 v2 报错

v2 将 Application 改为实例模式(Application.Create()),静态 Application.Run() 已移除。参考老教程时需区分版本差异。

列表数据修改后不刷新

修改 List 内容后必须调用 SetSource() 才能更新视图。也可自行实现 INotifyCollectionChanged 完成真正的 MVVM 绑定。

鼠标点击无响应

确保 app.Init() 执行后再创建组件。Linux 部分终端模拟器需开启鼠标报告功能,Windows Terminal 默认已支持。

总结

从安装 Terminal.Gui 到跑通 Hello World,再到搭建完整的任务管理面板,核心流程就是三步:创建窗口 → 使用 Pos/Dim 布局 → 绑定事件

后续可探索的方向:

  • TableView 构建数据表格(适合日志查看器、监控面板)
  • DialogWizard 实现多步引导流程
  • 查阅 Configuration 文档,将主题和快捷键持久化存储

Terminal.Gui 仓库拥有 11000+ Star,文档完善且社区活跃。下次编写运维脚本或内部工具时,尝试添加终端 UI 提升使用体验。

仓库地址: https://github.com/tui-cs/Terminal.Gui

最后更新:2026-06-26T10:03:42

评论 (0)

发表评论

blog.comments.form.loading
0/500
加载评论中...