c#更新时闪烁的Listview

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/442817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:32:34  来源:igfitidea点击:

c# flickering Listview on update

c#listviewflicker

提问by Brad

I have a list view that is periodically updated (every 60 seconds). It was anoying to me that i would get a flicker every time it up dated. The method being used was to clear all the items and then recreate them. I decided to instead of clearing the items I would just write directly to the cell with the new text. Is this a better approach or does anyone have a better solution.

我有一个定期更新的列表视图(每 60 秒)。每次更新时我都会闪烁,这对我来说很烦人。使用的方法是清除所有项目,然后重新创建它们。我决定不清除项目,而是直接将新文本写入单元格。这是更好的方法还是有人有更好的解决方案。

采纳答案by Stormenet

The ListView control has a flicker issue. The problem appears to be that the control's Update overload is improperly implemented such that it acts like a Refresh. An Update should cause the control to redraw only its invalid regions whereas a Refresh redraws the control's entire client area. So if you were to change, say, the background color of one item in the list then only that particular item should need to be repainted. Unfortunately, the ListView control seems to be of a different opinion and wants to repaint its entire surface whenever you mess with a single item… even if the item is not currently being displayed. So, anyways, you can easily suppress the flicker by rolling your own as follows:

ListView 控件存在闪烁问题。问题似乎是控件的更新重载未正确实现,以至于它的行为类似于刷新。更新应使控件仅重绘其无效区域,而刷新应重绘控件的整个客户区。因此,如果您要更改,例如,列表中一项的背景颜色,则只需要重新绘制该特定项。不幸的是,ListView 控件似乎有不同的意见,并且希望在您弄乱单个项目时重新绘制其整个表面……即使该项目当前未显示。因此,无论如何,您可以通过滚动自己的方式轻松抑制闪烁,如下所示:

class ListViewNF : System.Windows.Forms.ListView
{
    public ListViewNF()
    {
        //Activate double buffering
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form's WndProc
        this.SetStyle(ControlStyles.EnableNotifyMessage, true);
    }

    protected override void OnNotifyMessage(Message m)
    {
        //Filter out the WM_ERASEBKGND message
        if(m.Msg != 0x14)
        {
            base.OnNotifyMessage(m);
        }
    }
}

From: Geekswithblogs.net

来自:Geekswithblogs.net

回答by Gonzalo Quero

回答by Ironicnet

Try setting the double buffered property in true.

尝试将双缓冲属性设置为 true。

Also you could use:

你也可以使用:

this.SuspendLayout();

//update control

this.ResumeLayout(False);

this.PerformLayout();

回答by Marc Gravell

In addition to the other replies, many controls have a [Begin|End]Update()method that you can use to reduce flickering when editing the contents - for example:

除了其他回复之外,许多控件都有一种[Begin|End]Update()方法,您可以使用它来减少编辑内容时的闪烁 - 例如:

    listView.BeginUpdate();
    try {
        // listView.Items... (lots of editing)
    } finally {
        listView.EndUpdate();
    }

回答by Jon Cage

Excellent question and Stormenent's answer was spot on. Here's a C++ port of his code for anyone else who might be tackling C++/CLI implementations.

很好的问题,Stormenent 的回答很到位。这是他的代码的 C++ 端口,供其他可能处理 C++/CLI 实现的人使用。

#pragma once

#include "Windows.h" // For WM_ERASEBKGND

using namespace System;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

public ref class FlickerFreeListView : public ListView
{
public:
    FlickerFreeListView()
    {
        //Activate double buffering
        SetStyle(ControlStyles::OptimizedDoubleBuffer | ControlStyles::AllPaintingInWmPaint, true);

        //Enable the OnNotifyMessage event so we get a chance to filter out 
        // Windows messages before they get to the form's WndProc
        SetStyle(ControlStyles::EnableNotifyMessage, true);
    }

protected:
    virtual  void OnNotifyMessage(Message m) override
    {
        //Filter out the WM_ERASEBKGND message
        if(m.Msg != WM_ERASEBKGND)
        {
            ListView::OnNotifyMessage(m);
        }
    }

};

回答by Sebastien GISSINGER

If this can help, the following component solved my ListView flickering issues with .NET 3.5

如果这有帮助,以下组件解决了我的 ListView 与 .NET 3.5 闪烁的问题

[ToolboxItem(true)]
[ToolboxBitmap(typeof(ListView))]
public class ListViewDoubleBuffered : ListView
{
    public ListViewDoubleBuffered()
    {
        this.DoubleBuffered = true;
    }
}

I use it in conjonction with .BeginUpdate() and .EndUpdate() methods where I do ListView.Items manipulation.

我将它与 .BeginUpdate() 和 .EndUpdate() 方法结合使用,我在其中执行 ListView.Items 操作。

I don't understand why this property is a protected one...even in the .NET 4.5 (maybe a security issue)

我不明白为什么这个属性是受保护的……即使在 .NET 4.5 中(可能是一个安全问题)

回答by jaiveeru

Simple solution

简单的解决方案

yourlistview.BeginUpdate()

//Do your update of adding and removing item from the list

yourlistview.EndUpdate()

回答by Sifty

The simplest Solution would probably be using

最简单的解决方案可能是使用

       listView.Items.AddRange(listViewItems.ToArray());

instead of

代替

       foreach (ListViewItem listViewItem in listViewItems)
       {
           listView.Items.Add(listViewItem);
       }

This works way better.

这效果更好。

回答by Chris Parker

I know this is an extremelyold question and answer. However, this is the top result when searching for "C++/cli listview flicker" - despite the fact that this isn't even talking about C++. So here's the C++ version of this:

我知道这是一个非常古老的问题和答案。然而,这是搜索“C++/cli listview flicker”时的最佳结果——尽管这甚至不是在谈论 C++。所以这是它的 C++ 版本:

I put this in the header file for my main form, you can choose to put it elsewhere...

我把它放在我的主窗体的头文件中,你可以选择把它放在其他地方......

static void DoubleBuffer(Control^ control, bool enable) {
    System::Reflection::PropertyInfo^ info = control->GetType()->
        GetProperty("DoubleBuffered", System::Reflection::BindingFlags::Instance 
            | System::Reflection::BindingFlags::NonPublic);
    info->SetValue(control, enable, nullptr);
}

If you happen to land here looking for a similar answer for managed C++, that works for me. :)

如果您碰巧来到这里为托管 C++ 寻找类似的答案,那对我有用。:)

回答by Suresh Balaraman

In Winrt Windows phone 8.1 you can set the following code to fix this issue.

在 Winrt Windows phone 8.1 中,您可以设置以下代码来解决此问题。

<ListView.ItemContainerTransitions>
    <TransitionCollection/>      
</ListView.ItemContainerTransitions>