超简单!C#上位机必备技能之实时日志
大家好!我是付工。
我个人开发上位机的习惯是,如果条件允许,主界面一定要有日志的一席之地。
上位机使用者大都是非技术人员,他们通常缺乏专业的系统诊断能力,清晰的日志能够以直观的语言(如“设备X通信失败,请检查网线连接”)替代晦涩的错误代码,帮助他们快速理解问题,也减少了一些不必要的沟通成本。
今天给大家分享如何实现上位机通用日志系统。
一、日志界面
我一般情况下会使用ListView来做日志。
1、日志界面设计。
- 拖放一个ListView控件到界面上。
-
将背景颜色设置为主窗体一致。
-
点击右上方三角,选择编辑列,添加两列,分别是日期时间和日志内容。
这样我们的日志界面就设计好了。

2、设置日志的图标显示。
-
准备3个图标,对应Info、Warning、Error。

-
拖放一个ImageList组件到界面上。
-
将3个图标文件添加到ImageList里,这里按照日志等级顺序添加。

-
点击ListView右上角三角,将视图设置为Details,小ImageList选择上面准备好的ImageList组件。

-
将HeaderStyle设置为None,然后创建几个按钮,为后面测试做准备。

二、日志开发
1、创建一个日志等级枚举LogLevel,分别为信息、警告、错误。
/// 日志等级枚举
/// </summary>
public enum LogLevel
{
信息,
警告,
错误
}
2、创建一个日志管理类LogManager,代码如下:
public class LogManager
{
// 单例实例
private static readonly LogManager instance = new LogManager();
// 日志委托
public Action<LogLevel, string> AddLog;
// 私有构造函数(防止外部创建实例)
private LogManager()
{
}
/// <summary>
/// 全局访问点
/// </summary>
public static LogManager Instance => instance;
/// <summary>
/// 记录日志
/// </summary>
/// <param name="level">日志等级</param>
/// <param name="message">日志内容</param>
public void Log(LogLevel level, string message)
{
// 触发事件,通知UI更新(跨线程安全)
AddLog?.Invoke(level, message);
}
}
3、在日志所在界面编写一个AddLog方法,代码如下:
private void AddLog(LogLevel level, string message)
{
// 跨线程判断
if (this.lst_View.InvokeRequired)
{
this.lst_View.Invoke(new Action<LogLevel, string>(AddLog), level, message);
return;
}
else
{
// 创建列表项
ListViewItem item = new ListViewItem(" " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), (int)level);
item.SubItems.Add(message);
// 根据日志等级设置颜色
switch (level)
{
case LogLevel.错误:
item.ForeColor = System.Drawing.Color.Red;
break;
case LogLevel.警告:
item.ForeColor = System.Drawing.Color.Orange;
break;
default:
item.ForeColor = System.Drawing.Color.Black;
break;
}
//如果希望最新的日志自动滚动到最后
this.lst_View.Items.Add(item);
this.lst_View.EnsureVisible(this.lst_View.Items.Count - 1);
//如果希望最新的日志在最前面
//this.lst_View.Items.Insert(0, item);
}
}
-
加跨线程访问判断,否则多线程调用会报错。
-
代码中提供了两种日志显示的方法,一种是最新日志在最后并自动滚动,一种是最新日志在最前面,根据个人习惯选择。
-
日期时间那里加了空格,避免与图标过于靠近。
三、日志使用
1、我们希望在哪个窗体中使用日志,那么在初始化时,添加以下代码,进行委托绑定。
LogManager.Instance.AddLog = this.AddLog;
2、然后就可以调用了,下面不同按钮调用不同的日志类型信息:
private void btn_Info_Click(object sender, EventArgs e)
{
LogManager.Instance.Log(LogLevel.信息, "这是一条正常信息");
}
private void btn_Warn_Click(object sender, EventArgs e)
{
LogManager.Instance.Log(LogLevel.警告, "这是一条警告信息");
}
private void btn_Error_Click(object sender, EventArgs e)
{
LogManager.Instance.Log(LogLevel.错误, "这是一条错误信息");
}
3、运行软件,分别点击3个按钮,运行效果如下:

4、当日志内容比较多的话,会出现这种情况:

对这个问题的解决方案分为两步:
1、窗体初始化动态设置第2列的宽度。
this.lst_View.Columns[1].Width = this.lst_View.Width - this.lst_View.Columns[0].Width-20;
2、设置ListView的ShowItemToolTips为True。

感谢阅读和关注,后续跟大家分享如何进行日志存储和多行显示。
更多推荐


所有评论(0)