2

C# .Net 4.5

I have a ListView that is constantly being updated by different threads through this method:

public void UpdateUI_List_SetRow(int rowNum, ListViewItem item)
{
    lock (lock_List)
    {
        try
        {
            if (this.lstStatus.InvokeRequired)
                lstStatus.Invoke(new MethodInvoker(() => lstStatus.Items[rowNum] = item));
            else
                lstStatus.Items[rowNum] = item;
        }
        catch (Exception ex)
        {
            ErrorLogging.Log(ex);
        }
    }
}

It constantly flickers while being updated. I have tried the DoubleBuffered fix (How to prevent flickering in ListView when updating a single ListViewItem's text?) but it didn't work.

Sorry if this is a duplicate post but I couldn't find any solution other than enabling double buffering.

Community
  • 1
  • 1
blizz
  • 4,102
  • 6
  • 36
  • 60
  • 2
    If your updates are too fast maybe you could write your fast, background updates to some collection. Then every 500 ms to 1000 ms update your ListView based on that collection. – Brad Feb 18 '14 at 23:32
  • ..and calling `SuspendLayout` and `ResumeLayout` may help too. – Simon Whitehead Feb 18 '14 at 23:41
  • suspendlayout did not make a difference. ugh..guess i'll have to try recoding it and see if it makes a difference :( – blizz Feb 18 '14 at 23:45

2 Answers2

6

Subclass ListView to enable double buffering:

namespace System.Windows.Forms
{
    public class ListViewEx : ListView
    {
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
                return cp;
            }
        }
    }
}
JonPall
  • 814
  • 4
  • 9
  • could you elaborate on what is happening here a bit more? – Brad Feb 19 '14 at 00:08
  • Does this enable a different double buffering mechanism than the link I provided in my question? – blizz Feb 19 '14 at 00:14
  • 1
    ListView is poorly implemented in such a way that it will redraw it's whole client area each time an item is added or removed. Which causes the flickering. And that in turn also invalidates the background, which is why you experience the flickering. – JonPall Feb 19 '14 at 00:15
  • Looks like using this subclass did the trick! Thank you good sir! – blizz Feb 19 '14 at 00:20
  • Yes, it enforces bottom-up painting. Clipping areas already painted from subsequent update regions. Hence the background will be painted around the items. – JonPall Feb 19 '14 at 00:20
3

Code provided in accepted answer works, but ruins selection rectangle. The solution below works like a charm. It enables double buffering and retains correct rectangle.

public partial class myListView : ListView
{
    public myListView()
    {
        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
    }
}

How to use it - add this code to your namespace and use myListView instead of conventional ListView.

enter image description here

Creek Drop
  • 464
  • 3
  • 13