c#在更新时闪烁列表视图

Bra*_*rad 50 c# listview flicker

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

Sto*_*net 91

ListView控件有一个闪烁问题.问题似乎是控件的Update重载不正确地实现,使其像Refresh一样运行.更新应该使控件仅重绘其无效区域,而刷新重绘控件的整个客户区域.因此,如果您要更改列表中某个项目的背景颜色,则只需要重新绘制该特定项目.不幸的是,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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

来自:Geekswithblogs.net

  • 如果你不喜欢这个解决方案,因为子类化,这里非常类似,没有子类化:http://stackoverflow.com/questions/87795/how-to-prevent-flickering-in-listview-when-updating-a-单listviewitems文本 (4认同)
  • OptimizedDoubleBuffer可以正常工作.但我不认为跳过对base.OnNotifyMessage(m)的调用有任何帮助.我只是检查了ILSpy和Control.OnNotifyMessage有一个空的实现.来自MSDN:"当在派生类中重写OnNotifyMessage时,不需要调用基类的OnNotifyMessage方法,因为没有初始实现." 此方法存在,因此可以在处理消息时通知子类.如果您需要更改这些消息,您需要覆盖WndProc吗? (3认同)

Mar*_*ell 22

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

    listView.BeginUpdate();
    try {
        // listView.Items... (lots of editing)
    } finally {
        listView.EndUpdate();
    }
Run Code Online (Sandbox Code Playgroud)

  • 我发现这有帮助,但不能完全消除闪烁。 (3认同)

Wra*_*ath 9

这是我的C#实现的快速解决方案,该实现不需要子类化列表视图等。

使用反射将DoubleBuffered属性设置为尝试在窗体构造函数中使用。

    lvMessages
        .GetType()
        .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        .SetValue(lvMessages, true, null);
Run Code Online (Sandbox Code Playgroud)


Gon*_*ero 5

是的,让它双倍缓冲.它会减少闪烁;)http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.doublebuffered.aspx

  • -1,因为你可以设置它,如果从中派生出一个新类,还有"SetStyle"方法.但是在向某人投票之前进行研究的方法,即使你回答使用你的评论毫无意义的确切原因*竖起大拇指* (2认同)

Jon*_*age 5

精彩的问题和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);
        }
    }

};
Run Code Online (Sandbox Code Playgroud)


Seb*_*GER 5

如果这可以解决问题,则以下组件解决了.NET 3.5的ListView闪烁问题。

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

我将它与ListView.Items操作的.BeginUpdate()和.EndUpdate()方法配合使用。

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