10分钟上手 Terminal.Gui:搭建终端任务管理面板
从零学习用 C# + Terminal.Gui 搭建交互式终端应用,涵盖窗口创建、相对布局、列表数据绑定与事件处理,可用于运维工具和 CLI 管理面板开发。
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构建数据表格(适合日志查看器、监控面板)Dialog和Wizard实现多步引导流程- 查阅
Configuration文档,将主题和快捷键持久化存储
Terminal.Gui 仓库拥有 11000+ Star,文档完善且社区活跃。下次编写运维脚本或内部工具时,尝试添加终端 UI 提升使用体验。