当前位置:  开发笔记 > 编程语言 > 正文

更新单个ListViewItem的文本时如何防止ListView中的闪烁?

如何解决《更新单个ListViewItem的文本时如何防止ListView中的闪烁?》经验,为你挑选了4个好方法。

我想要的只是更新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);
}

他们说这解决了问题,但在我的情况下却没有.我相信这是因为我在每个项目上使用图标.



1> Oliver..:

接受的答案是有效的,但是相当冗长,并且从控制中得到(如在其他答案中提到的)只是为了实现双缓冲也有点过头了.但幸运的是我们有反思,如果我们愿意,也可以调用内部方法(但要确定你做了什么!).

将这种方法封装到扩展方法中,我们将获得一个非常短的类:

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

所有的闪烁都消失了.

更新

我偶然发现了这个问题,由于这个事实,扩展方法应该(可能)更好:

public static void DoubleBuffered(this Control control, bool enable)
{
    var doubleBufferPropertyInfo = control.GetType().GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic);
    doubleBufferPropertyInfo.SetValue(control, enable, null);
}


我也会选择这个 - 反射在大多数时候是一个邪恶的黑客,但这是一个很好的利用它.

2> Jonas..:

要结束这个问题,这里有一个辅助类,当为表单中的每个ListView或任何其他ListView派生控件加载表单时,应该调用该辅助类.感谢"Brian Gillespie"提供解决方案.

public enum ListViewExtendedStyles
{
    /// 
    /// LVS_EX_GRIDLINES
    /// 
    GridLines = 0x00000001,
    /// 
    /// LVS_EX_SUBITEMIMAGES
    /// 
    SubItemImages = 0x00000002,
    /// 
    /// LVS_EX_CHECKBOXES
    /// 
    CheckBoxes = 0x00000004,
    /// 
    /// LVS_EX_TRACKSELECT
    /// 
    TrackSelect = 0x00000008,
    /// 
    /// LVS_EX_HEADERDRAGDROP
    /// 
    HeaderDragDrop = 0x00000010,
    /// 
    /// LVS_EX_FULLROWSELECT
    /// 
    FullRowSelect = 0x00000020,
    /// 
    /// LVS_EX_ONECLICKACTIVATE
    /// 
    OneClickActivate = 0x00000040,
    /// 
    /// LVS_EX_TWOCLICKACTIVATE
    /// 
    TwoClickActivate = 0x00000080,
    /// 
    /// LVS_EX_FLATSB
    /// 
    FlatsB = 0x00000100,
    /// 
    /// LVS_EX_REGIONAL
    /// 
    Regional = 0x00000200,
    /// 
    /// LVS_EX_INFOTIP
    /// 
    InfoTip = 0x00000400,
    /// 
    /// LVS_EX_UNDERLINEHOT
    /// 
    UnderlineHot = 0x00000800,
    /// 
    /// LVS_EX_UNDERLINECOLD
    /// 
    UnderlineCold = 0x00001000,
    /// 
    /// LVS_EX_MULTIWORKAREAS
    /// 
    MultilWorkAreas = 0x00002000,
    /// 
    /// LVS_EX_LABELTIP
    /// 
    LabelTip = 0x00004000,
    /// 
    /// LVS_EX_BORDERSELECT
    /// 
    BorderSelect = 0x00008000,
    /// 
    /// LVS_EX_DOUBLEBUFFER
    /// 
    DoubleBuffer = 0x00010000,
    /// 
    /// LVS_EX_HIDELABELS
    /// 
    HideLabels = 0x00020000,
    /// 
    /// LVS_EX_SINGLEROW
    /// 
    SingleRow = 0x00040000,
    /// 
    /// LVS_EX_SNAPTOGRID
    /// 
    SnapToGrid = 0x00080000,
    /// 
    /// LVS_EX_SIMPLESELECT
    /// 
    SimpleSelect = 0x00100000
}

public enum ListViewMessages
{
    First = 0x1000,
    SetExtendedStyle = (First + 54),
    GetExtendedStyle = (First + 55),
}

/// 
/// Contains helper methods to change extended styles on ListView, including enabling double buffering.
/// Based on Giovanni Montrone's article on 
/// 
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);
    }
}



3> Brian Gilles..:

CommonControls 6中的ListView(XP或更新版本)支持双缓冲.幸运的是,.NET将最新的CommonControl包装在系统上.要启用双缓冲,请将相应的Windows消息发送到ListView控件.

以下是详细信息:http: //www.codeproject.com/KB/list/listviewxp.aspx



4> Rolf Kristen..:

在.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

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有