C# Mono程序ListView子项Linux不显示但Windows正常问题求助
Mono下ListView子项不显示的问题排查与修复
问题根源分析
你的代码在Windows下正常但Mono下失效,核心问题出在跨线程UI操作的拆分执行和ListView项集合的错误操作方式:
- 你把
BeginUpdate和后续的AddRange、EndUpdate拆成了两次独立的Invoke调用,Mono的WinForms实现对UI更新的状态管理更严格,这种拆分导致ListView无法正确完成更新流程,进而无法触发重绘。 - 新建
ListView.ListViewItemCollection实例来添加项的方式不符合Mono的控件逻辑,应该直接操作ListView自带的Items集合。 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
相关产品推荐
相关产品推荐

