我想要的只是更新ListViewItem的文本,而不会看到任何闪烁。
这是我的更新代码(多次调用):
listView.BeginUpdate();
listViewItem.SubItems[0].Text = state.ToString(); // update the state
listViewItem.SubItems[1].Text = progress.ToString(); // update the progress
listView.EndUpdate();
我见过一些涉及覆盖组件WndProc():
protected override void WndProc(ref Message m)
{
if (m.Msg == (int)WM.WM_ERASEBKGND)
{
m.Msg = (int)IntPtr.Zero;
}
base.WndProc(ref m);
}
他们说它解决了问题,但在我的情况下它没有。我相信这是因为我在每个项目上使用图标。
答案 0 :(得分:60)
接受的答案有效,但是相当冗长,并且从控制中获得(如在其他答案中提到的)只是为了实现双缓冲也有点过头了。但幸运的是我们有反思,如果我们愿意,也可以调用内部方法(但要确定你做了什么!)。
将这种方法封装到扩展方法中,我们将得到一个非常短的类:
public static class ControlExtensions
{
public static void DoubleBuffering(this Control control, bool enable)
{
var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic);
method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable });
}
}
可以在我们的代码中轻松调用:
InitializeComponent();
myListView.DoubleBuffering(true); //after the InitializeComponent();
所有的闪烁都消失了。
我偶然发现this question并且由于这个事实,扩展方法应该(可能)更好:
public static void DoubleBuffered(this Control control, bool enable)
{
var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
doubleBufferPropertyInfo.SetValue(control, enable, null);
}
答案 1 :(得分:51)
要结束这个问题,这里有一个辅助类,当为表单中的每个ListView或任何其他ListView派生控件加载表单时,应该调用该辅助类。感谢“Brian Gillespie”提供解决方案。
public enum ListViewExtendedStyles
{
/// <summary>
/// LVS_EX_GRIDLINES
/// </summary>
GridLines = 0x00000001,
/// <summary>
/// LVS_EX_SUBITEMIMAGES
/// </summary>
SubItemImages = 0x00000002,
/// <summary>
/// LVS_EX_CHECKBOXES
/// </summary>
CheckBoxes = 0x00000004,
/// <summary>
/// LVS_EX_TRACKSELECT
/// </summary>
TrackSelect = 0x00000008,
/// <summary>
/// LVS_EX_HEADERDRAGDROP
/// </summary>
HeaderDragDrop = 0x00000010,
/// <summary>
/// LVS_EX_FULLROWSELECT
/// </summary>
FullRowSelect = 0x00000020,
/// <summary>
/// LVS_EX_ONECLICKACTIVATE
/// </summary>
OneClickActivate = 0x00000040,
/// <summary>
/// LVS_EX_TWOCLICKACTIVATE
/// </summary>
TwoClickActivate = 0x00000080,
/// <summary>
/// LVS_EX_FLATSB
/// </summary>
FlatsB = 0x00000100,
/// <summary>
/// LVS_EX_REGIONAL
/// </summary>
Regional = 0x00000200,
/// <summary>
/// LVS_EX_INFOTIP
/// </summary>
InfoTip = 0x00000400,
/// <summary>
/// LVS_EX_UNDERLINEHOT
/// </summary>
UnderlineHot = 0x00000800,
/// <summary>
/// LVS_EX_UNDERLINECOLD
/// </summary>
UnderlineCold = 0x00001000,
/// <summary>
/// LVS_EX_MULTIWORKAREAS
/// </summary>
MultilWorkAreas = 0x00002000,
/// <summary>
/// LVS_EX_LABELTIP
/// </summary>
LabelTip = 0x00004000,
/// <summary>
/// LVS_EX_BORDERSELECT
/// </summary>
BorderSelect = 0x00008000,
/// <summary>
/// LVS_EX_DOUBLEBUFFER
/// </summary>
DoubleBuffer = 0x00010000,
/// <summary>
/// LVS_EX_HIDELABELS
/// </summary>
HideLabels = 0x00020000,
/// <summary>
/// LVS_EX_SINGLEROW
/// </summary>
SingleRow = 0x00040000,
/// <summary>
/// LVS_EX_SNAPTOGRID
/// </summary>
SnapToGrid = 0x00080000,
/// <summary>
/// LVS_EX_SIMPLESELECT
/// </summary>
SimpleSelect = 0x00100000
}
public enum ListViewMessages
{
First = 0x1000,
SetExtendedStyle = (First + 54),
GetExtendedStyle = (First + 55),
}
/// <summary>
/// Contains helper methods to change extended styles on ListView, including enabling double buffering.
/// Based on Giovanni Montrone's article on <see cref="http://www.codeproject.com/KB/list/listviewxp.aspx"/>
/// </summary>
public class ListViewHelper
{
private ListViewHelper()
{
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern int SendMessage(IntPtr handle, int messg, int wparam, int lparam);
public static void SetExtendedStyle(Control control, ListViewExtendedStyles exStyle)
{
ListViewExtendedStyles styles;
styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0);
styles |= exStyle;
SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles);
}
public static void EnableDoubleBuffer(Control control)
{
ListViewExtendedStyles styles;
// read current style
styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0);
// enable double buffer and border select
styles |= ListViewExtendedStyles.DoubleBuffer | ListViewExtendedStyles.BorderSelect;
// write new style
SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles);
}
public static void DisableDoubleBuffer(Control control)
{
ListViewExtendedStyles styles;
// read current style
styles = (ListViewExtendedStyles)SendMessage(control.Handle, (int)ListViewMessages.GetExtendedStyle, 0, 0);
// disable double buffer and border select
styles -= styles & ListViewExtendedStyles.DoubleBuffer;
styles -= styles & ListViewExtendedStyles.BorderSelect;
// write new style
SendMessage(control.Handle, (int)ListViewMessages.SetExtendedStyle, 0, (int)styles);
}
}
答案 2 :(得分:11)
CommonControls 6中的ListView(XP或更新版本)支持双缓冲。幸运的是,.NET将最新的CommonControl包装在系统上。要启用双缓冲,请将相应的Windows消息发送到ListView控件。
答案 3 :(得分:10)
在.NET Winforms 2.0中,存在一个名为DoubleBuffered的受保护属性。
通过继承ListView,可以将此protected属性设置为true。这将启用双缓冲,而无需调用SendMessage。
设置DoubleBuffered属性与设置以下样式相同:
listview.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=94096
答案 4 :(得分:2)
我知道这个问题已经很老了,但因为这是谷歌的第一个搜索结果之一,我想分享我的修复。
我可以消除100%闪烁的唯一方法是结合Oliver(扩展类和双缓冲)的答案并使用BeignUpdate()
和EndUpdate()
方法。
他们中的任何一个都不能解决我的闪烁问题。 当然,我使用了一个非常复杂的列表,我需要将其推入列表中,并且几乎每一秒都需要更新它。
答案 5 :(得分:1)
这会有所帮助:
class DoubleBufferedListView : System.Windows.Forms.ListView
{
public DoubleBufferedListView()
:base()
{
this.DoubleBuffered = true;
}
}
答案 6 :(得分:1)
yourlistview.BeginUpdate()
//您在列表中添加和删除项目的更新
yourlistview.EndUpdate()
答案 7 :(得分:0)
如果您只想更新文本,只需直接设置更改的SubItem文本,而不是更新整个ListViewItem(您没有说明您的更新方式)。
您显示的覆盖相当于简单地覆盖OnPaintBackground,这将是执行该任务的“更正确”的托管方式,并且它对单个项目没有帮助。
如果您仍有问题,我们需要澄清您实际尝试的内容。
答案 8 :(得分:0)
这是在黑暗中拍摄的,但您可以尝试双重缓冲控件。
SetStyle(
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.DoubleBuffer, true)
答案 9 :(得分:0)
在设置任何列表视图项之前调用ListView上的BeginUpdate()方法,然后仅在添加所有项后调用EndUpdate()。
这将阻止闪烁。