【问题标题】:Cannot get ListView to stop flickering无法让 ListView 停止闪烁
【发布时间】:2014-03-19 00:49:53
【问题描述】:

C# .Net 4.5

我有一个 ListView,它通过这个方法被不同的线程不断更新:

public void UpdateUI_List_SetRow(int rowNum, ListViewItem item)
{
    lock (lock_List)
    {
        try
        {
            if (this.lstStatus.InvokeRequired)
                lstStatus.Invoke(new MethodInvoker(() => lstStatus.Items[rowNum] = item));
            else
                lstStatus.Items[rowNum] = item;
        }
        catch (Exception ex)
        {
            ErrorLogging.Log(ex);
        }
    }
}

它在更新时不断闪烁。我已经尝试过 DoubleBuffered 修复 (How to prevent flickering in ListView when updating a single ListViewItem's text?),但它没有用。

对不起,如果这是一个重复的帖子,但除了启用双缓冲之外我找不到任何解决方案。

【问题讨论】:

  • 如果您的更新太快,也许您可​​以将您的快速后台更新写入某个集合。然后每 500 毫秒到 1000 毫秒根据该集合更新您的 ListView。
  • ..并致电 SuspendLayout 和 ResumeLayout 也可能有所帮助。
  • suspendlayout 没有任何区别。呃..我想我得试着重新编码一下,看看它是否有所作为:(

标签: c# .net multithreading listview


【解决方案1】:

子类 ListView 以启用双缓冲:

namespace System.Windows.Forms
{
    public class ListViewEx : ListView
    {
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
                return cp;
            }
        }
    }
}

【讨论】:

  • 您能否详细说明这里发生的事情?
  • 这是否启用了与我在问题中提供的链接不同的双缓冲机制?
  • ListView 的实现很糟糕,以至于每次添加或删除项目时它都会重新绘制整个客户区。导致闪烁。这反过来也会使背景无效,这就是您体验闪烁的原因。
  • 看起来使用这个子类成功了!谢谢你好先生!
  • 是的,它强制执行自下而上的绘制。已从后续更新区域绘制的剪切区域。因此,将在项目周围绘制背景。
【解决方案2】:

已接受答案中提供的代码有效,但会破坏选择矩形。下面的解决方案就像一个魅力。它启用双缓冲并保留正确的矩形。

public partial class myListView : ListView
{
    public myListView()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    }
}

如何使用它 - 将此代码添加到您的命名空间并使用 myListView 而不是传统的 ListView。

【讨论】:

    猜你喜欢
    • 2015-11-05
    • 2010-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-04
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    相关资源
    最近更新 更多