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
c# flickering Listview on update
提问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
回答by Gonzalo Quero
Yes, make it double buffered. It will reduce the flicker ;) http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.doublebuffered.aspx
是的,让它双缓冲。它将减少闪烁;) http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.doublebuffered.aspx
回答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>