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

c# listview flicker

45030 观看

13回复

7789 作者的声誉

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

作者: Brad 的来源 发布者: 2009 年 1 月 14 日

回应 13


89

16197 作者的声誉

决定

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);
        }
    }
}

来自:Geekswithblogs.net

作者: Stormenet 发布者: 2009 年 1 月 14 日

5

3039 作者的声誉

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

作者: Gonzalo Quero 发布者: 2009 年 1 月 14 日

0

500 作者的声誉

尝试将double buffered属性设置为true。

你也可以使用:

this.SuspendLayout();

//update control

this.ResumeLayout(False);

this.PerformLayout();
作者: Ironicnet 发布者: 2009 年 1 月 14 日

22

813165 作者的声誉

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

    listView.BeginUpdate();
    try {
        // listView.Items... (lots of editing)
    } finally {
        listView.EndUpdate();
    }
作者: Marc Gravell 发布者: 2009 年 1 月 14 日

4

22470 作者的声誉

很好的问题和Stormenent的回答是现场。对于可能正在处理C ++ / CLI实现的任何其他人来说,这是他的代码的C ++端口。

#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);
        }
    }

};
作者: Jon Cage 发布者: 2010 年 7 月 15 日

5

547 作者的声誉

如果这可以提供帮助,则以下组件解决了.NET 3.5中的ListView闪烁问题

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

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

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

作者: Sebastien GISSINGER 发布者: 2012 年 12 月 17 日

1

87 作者的声誉

简单解决方案

yourlistview.BeginUpdate()

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

yourlistview.EndUpdate()
作者: jaiveeru 发布者: 2014 年 8 月 20 日

3

31 作者的声誉

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

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

代替

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

这种方式更好。

作者: Sifty 发布者: 2015 年 5 月 8 日

0

161 作者的声誉

我知道这是一个非常古老的问答。然而,这是搜索“C ++ / cli listview flicker”时的最佳结果 - 尽管事实上这甚至都不是在讨论C ++。所以这是这个的C ++版本:

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

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);
}

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

作者: Chris Parker 发布者: 2016 年 10 月 27 日

0

80 作者的声誉

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

<ListView.ItemContainerTransitions>
    <TransitionCollection/>      
</ListView.ItemContainerTransitions>
作者: Suresh Balaraman 发布者: 2016 年 11 月 28 日

6

14055 作者的声誉

这是我对C#实现的快速修复,它不需要对列表视图进行子类化等。

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

    lvMessages
        .GetType()
        .GetProperty("DoubleBuffered", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
        .SetValue(lvMessages, true, null);
作者: WraithNath 发布者: 2017 年 2 月 22 日

2

696 作者的声誉

您可以使用以下扩展类将DoubleBuffered属性设置为true

using System.Reflection;

public static class ListViewExtensions
{
    public static void SetDoubleBuffered(this ListView listView, bool value)
    {
        listView.GetType()
            .GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(listView, value);
    }
}
作者: Ghost4Man 发布者: 2018 年 4 月 27 日

0

1001 作者的声誉

对于它的价值,在我的情况下,我只需要添加一个电话

Application.EnableVisualStyles()

在运行应用程序之前,像这样:

    private static void Main()
    {
        Application.EnableVisualStyles();
        Application.Run(new Form1());
    }

否则,双缓冲是不够的。也许这是一个非常古老的项目,新的项目默认设置为......

作者: Fred Mauroy 发布者: 2018 年 4 月 28 日
32x32