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

C# Mono程序ListView子项Linux不显示但Windows正常问题求助

Mono下ListView子项不显示的问题排查与修复

问题根源分析

你的代码在Windows下正常但Mono下失效,核心问题出在跨线程UI操作的拆分执行和ListView项集合的错误操作方式:

  1. 你把BeginUpdate和后续的AddRange、EndUpdate拆成了两次独立的Invoke调用,Mono的WinForms实现对UI更新的状态管理更严格,这种拆分导致ListView无法正确完成更新流程,进而无法触发重绘。
  2. 新建ListView.ListViewItemCollection实例来添加项的方式不符合Mono的控件逻辑,应该直接操作ListView自带的Items集合。
  3. BeginUpdate的作用范围没有覆盖整个添加项的逻辑,导致控件的更新冻结状态没有被正确解除。

修复后的代码

将所有UI相关操作合并到同一个Invoke调用中,确保BeginUpdate、添加项、EndUpdate在同一个UI线程上下文完成:

private void AddLogsToScreen()
{
    // 复制日志数据,避免UI线程阻塞锁资源
    LogMutex.WaitOne();
    Stack<string[]> logListCopy = new Stack<string[]>(new Stack<string[]>(LogList));
    Console.WriteLine("LLC: " + string.Join(" , ", logListCopy.Peek()));
    LogMutex.ReleaseMutex();

    var allItemsToAdd = new List<ListViewItem>();
    int totalLogs = logListCopy.Count;
    for (int logNum = 0; logNum < totalLogs; logNum++)
    {
        string[] log = logListCopy.Pop();
        string[] deepLogCopy = new string[8];
        log.CopyTo(deepLogCopy, 0);

        deepLogCopy[2] = DateTime.Parse(log[2]).ToString("dd-MM-yyyy, hh:mm:ss tt");
        ListViewItem eachRow = new ListViewItem(deepLogCopy);
        Console.WriteLine("ListViewItem eachRow: " + string.Join(" , ", eachRow.SubItems.Cast<ListViewItem.ListViewSubItem>().Select(s => s.Text)));
        
        if (deepLogCopy[4] == "3") // Warning
            eachRow.BackColor = Color.Yellow;
        else if (deepLogCopy[4] == "4") // Error
            eachRow.BackColor = Color.Red;
            
        allItemsToAdd.Add(eachRow);
    }

    // 所有UI操作合并到一个Invoke中
    if (HUBsLogsListView.InvokeRequired)
    {
        HUBsLogsListView.Invoke(new MethodInvoker(delegate
        {
            UpdateListViewItems(allItemsToAdd);
        }));
    }
    else
    {
        UpdateListViewItems(allItemsToAdd);
    }
}

// 提取UI更新逻辑为单独方法,确保流程完整
private void UpdateListViewItems(List<ListViewItem> itemsToAdd)
{
    HUBsLogsListView.BeginUpdate();
    try
    {
        HUBsLogsListView.Items.AddRange(itemsToAdd.ToArray());
    }
    finally
    {
        HUBsLogsListView.EndUpdate();
        // 可选:强制触发重绘,针对Mono的特殊情况
        HUBsLogsListView.Refresh();
    }
}

额外注意事项

  • Mono的WinForms对跨线程UI操作的容错性远低于Windows的.NET Framework,所有涉及UI控件的操作必须在同一个Invoke调用内完成,禁止拆分多个独立的Invoke操作。
  • 避免直接创建ListView.ListViewItemCollection实例,始终通过控件的Items属性操作项集合。
  • 如果修复后仍有重绘问题,可以尝试在EndUpdate后调用HUBsLogsListView.Refresh()强制控件重绘,或者检查ListView的View属性是否设置为Details(只有Details视图才会显示子项)。

内容的提问来源于stack exchange,提问作者bcraner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 17:33:25