c pound

I reject your reality and substitute my own!

  Home  |   Contact  |   Syndication    |   Login
  46 Posts | 0 Stories | 22 Comments | 41 Trackbacks

News

Archives

Image Galleries

Blog Communities

Blog is a stupid word

Lunch Hour

Resources

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:

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

posted on Monday, February 27, 2006 7:44 AM

Feedback

# re: ListView Flicker 5/21/2006 9:31 AM Jimmy
This didn't seem to work at all for me. It made no difference whatsoever. I'm not using .net 2, so I had to use ControlStyles.DoubleBuffer instead of ControlStyles.OptimizedDoubleBuffer - would that make difference or not?

# re: ListView Flicker 5/21/2006 9:53 AM Jimmy
I've put a sample app at the above URI if you had time to compare with what you did...

# re: ListView Flicker 5/21/2006 9:54 AM Jimmy
Hmm - the URI was associated with my name -- not the most obvious thing. The URI is: www.dgp.toronto.edu/~jtalbot/flickeringListview/FlickeringListviewDoubleBuffer.zip

# re: ListView Flicker 5/22/2006 7:37 AM Dan Koster
Hey Jimmy, I was using .net 2 when I wrote this, and it may just be an issue with that version of the framework. I don't remember. But, don't forget that you also need to set ControlStyles.UserPaint when using ControlStyles.DoubleBuffer, like this:

this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);

as referenced here:
http://msdn2.microsoft.com/en-us/library/system.windows.forms.controlstyles.aspx
and here:
http://msdn2.microsoft.com/en-us/library/system.windows.forms.control.setstyle.aspx


# re: ListView Flicker 8/14/2006 7:26 AM Matt Godbolt
Hi Dan,
Thanks for the post. I'm using version 2, and despite what MSDN says, if I use the UserPaint option then nothing appears in the listview. If I handle the OnPaint() and pass it along to the underlying listview control it still doesn't draw anything...any tips?

Everything's working, but I'm wary of relying on fringe behaviour like this (ie setting OptimizedDoubleBuffer and NOT UserPaint).

Thanks,

Matt

# re: ListView Flicker 8/14/2006 8:35 AM Dan Koster
Heya Matt,

UserPaint tells the control to not render anything because you’re going to draw your own custom ListView UI. That’s why nothing shows up when you set UserPaint to True. It’s blank because anything it draws would probably interfere with anything you might draw. What’s probably happening behind the scenes is a simple if(!UserPaint) in the ListView’s Paint function.

I can’t be sure what’s going wrong with your code without more details. But, I can tell you that the code above was actually working mere moments before I copy & pasted it. As far as fringe behavior… remember that this was a hack to work around a flaw in the framework.

# re: ListView Flicker 8/14/2006 9:33 PM Matt Godbolt
Thanks Dan - my code's a 100% copy and paste of your original code, and it's working fine. I'm just saying that if I OR in the ControlStyles.UserPaint flag as MSDN suggests I need to, then obviously I'm supposed to redraw the control myself. However, I don't really want to; I just want default drawing behaviour without flickering!

As it seems to be working without the UserPaint flag set (despite MSDN telling me it needs to be set) I think I'm going to leave it and keep my fingers crossed!

Thanks for the reply, and for the original post which has saved me from throwing my monitor out the window in frustration! :)


# re: ListView Flicker 8/15/2006 5:47 AM Dan Koster
NP, Matt! I'm glad to see someone found something useful on my blog. I guess I should start updating it again.

You're pretty safe to keep using whatever you can get to work. Microsoft is really good about not making changes at a later date that would break stuff that's working *right now* (even if what you've got working was a hack).

# re: ListView Flicker 10/3/2006 11:54 PM Gary McAllister
I found this useful too..

# re: ListView Flicker 11/4/2006 11:23 AM James Moore
Works for me too under .net 2 VS 2005. Thanks.

# re: ListView Flicker 1/2/2007 8:30 AM Happy joy joy
Worked for me as well.

Thanks alot !

# re: ListView Flicker 1/23/2007 5:38 AM James Wansley
Worked well for me too. Just out of curiosity, why does the constructor not call the base constructor?

# re: ListView Flicker 2/19/2007 8:03 AM Jeff Russo
I have been trying to get a Flicker-Free Listview for a while, this works great!!

Thank you very much.

# re: ListView Flicker 3/30/2007 12:40 PM James Wansley
Here is a new development. Adding an item to position 0 in the listview still causes a non-buffered redraw of the entire list of items. Is there a way around this?

Thanks,

# re: ListView Flicker 3/30/2007 1:02 PM Dan Koster
It would, wouldn't it. If you insert an item at position 0 then every following item will have to move down one row to make room. If you added an item at position 3 then items 4 through ListView.Items.Count - 1 would all shift down by one and have to be repainted.

Trust me. You don't want to "fix" this behavior. ;)

# re: ListView Flicker 3/30/2007 1:49 PM Dan Koster
On second thought, you’re probably talking about adding a new item at position 0 when that particular position is not actually being displayed. Why should it repaint the list if your view of the list is from, say, item 10 to item 20? Well, your view is based on index numbers not on actual items. So your view of the list is still from item 10 to item 20 except that now (after adding a new item 0) that view is of a slightly different set of items. Thus, they get repainted. You should be able to follow these steps to get around this and keep the same items in view after you have added one above:

1) call ListView.BeginUpdate()to suspend painting of the list
2) add your item(s)
3) call ListViewItem.EnsureVisible() on the item you wish to appear last in your view of the list (because this one will have been pushed off the bottom of the list by adding one above)
4) call ListViewItem.EnsureVisible() on the item you wish to be at the top of your view (otherwise the top item might only be partially in view)
5) call ListView.EndUpdate() to resume painting of the list

Of course, if the call to EndUpdate causes the list to paint then this whole exercise is useless. I haven’t tested it, so let me know if it doesn’t work.

# re: ListView Flicker 5/29/2007 7:23 PM joe
anyone able to convert and apply this to visual basic .net?


# re: ListView Flicker 9/30/2007 8:23 AM Karl
This works also fine in VB.NET. Thanks a million because it helped me alot!!!!



# re: ListView Flicker 10/23/2007 4:01 PM Tom
Really helpful here too, thanks a lot!

# re: ListView Flicker 11/17/2007 2:03 PM Glen
You can also just set this.DoubleBuffer = true in the constructor. I've used this in several projects and seems to work rather well too.

public class FlickerFreeListView : ListView
{
public FlickerFreeListView()
{
this.DoubleBuffered = true;
}
}


# re: ListView Flicker 2/13/2008 2:59 PM jcam
Freaking Awesome. Works Great.
I've been looking for this for two days. Whoo-hoo.

# re: ListView Flicker 2/14/2008 4:28 AM Magnus
Yes the shorter tip from Glen works great.

# re: ListView Flicker 2/14/2008 1:29 PM Hays Pinthapataya
Work well on VS2008/NET3.5. Good job! Super Thanks.

# re: ListView Flicker 3/12/2008 10:53 AM ItsME
Great...It works good in .net 2.0..How come you know about all these stuff...Please guide me in learning all these tricks..

Thanks..It saved a lot of time and works like a gem.

# re: ListView Flicker 4/23/2008 9:31 AM sasayu1983
Work well on VS2008 .net 3.5 ! Thanks

# re: ListView Flicker 4/23/2008 4:17 PM krc
Awesome!

It works like a charm. I have a monitor application that displays log messages at runtime. The listview flickering made th application look aweful. With this fix, the application looks great!!!

Thanks a lot.


# re: ListView Flicker 5/4/2008 4:25 AM MMH
Works perfectly !!

# re: ListView Flicker 5/11/2008 1:23 AM Greg
Awesome!

I'm using it with 3.5 Framework on a 64bit os and it works fine as well.

thanks for the contribution.

# re: ListView Flicker 6/19/2008 2:20 AM Sameer
I havent tried Dan's idea but Glens modification works very well!
Thanks

# re: ListView Flicker 7/10/2008 7:36 AM Rick
I'm using a ListBox (not a ListView) and unfortunately, even extending the ListBox class in the exact same manner, I'm still seeing flicker whenever items are drawn. Does this approach only work with ListViews?

UPDATE -- I just compiled, ran your example program, and it flickers very badly. I'm using .Net 2.0. I also had to add a call to Invoke in your sample code because you were making modifications to the UI on a non-UI thread.

# re: ListView Flicker 7/11/2008 6:40 AM Rick
I've discovered that rather than overriding OnNotifyMessage, I override WndProc(ref Message m), and this solves my problem.


# re: ListView Flicker 7/11/2008 7:10 AM Dan Koster
This approach, via OnNotifyMessage or WndProc, can be used to filter out the WM_ERASEBKGND message in a derived control of any type. I know it alleviates the flicker problem with the ListView control, but I haven't had need to try it with the ListBox. It should have the a similar effect on all list controls. A simpler solution might be to just try setting the ListBox's DoubleBuffered property to true.

Where did you need to add in a call to Invoke? Nothing in the sample code should need it... and indeed it seems to work as is for myself and everyone else.

# Something more, that was helpful for me : 7/15/2008 8:40 PM Mohammad Rastkar
With 'DoubleBuffered' true for your derived listview and the form that contains your listview, you can do onething more to really have smooth update of listview (maybe it's not suitable for some situations, like when you update listview with huge amount of data) :

Just before updating, hide the listview :

ListViewEx_control.Visible = false;

after that, show it again.

# re: ListView Flicker 7/16/2008 1:22 AM Ramaraju
It's Working Fine...

# Something more, that was helpful for me : 7/16/2008 3:13 AM Mohammad Rastkar
... Also I've tested suggestion in my last post, for 2000 items (adding separately) and then adjusting the listview, then it's work nice.

# re: ListView Flicker 7/22/2008 12:31 PM Sergey
You can always get around the protected aspect of Control.SetStyle with reflection. This means you don't need an extra derived type at all:

public class StyleHelper
{
public static void DisableFlicker(System.Windows.Forms.Control ctrl)
{
MethodInfo method = ctrl.GetType().GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(ctrl, new object[] { ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true });
}
}
}

Then just call StyleHelper.DisableFlicker(myList); and there you are.

-S

# re: ListView Flicker 8/27/2008 8:54 AM Jesse
Works great on a virtual list. Thanks lots for making my control smoother.

Post Feedback

Title:
Name:
Email: (never displayed)
Url:
Comments: 
Please add 3 and 5 and type the answer here: