UseItemStyleForSubItems Property of ListView Control Causes Flicker?

G

Guest

Through testing, I believe I've proven that setting UseItemStyleForSubItems = False on ListView controls introduces "screen flicker" whenever items/subitems are added or modified in a ListView. The "screen flicker" problem disappears when UseItemStyleForSubItems is set to True (the default setting)

Can anyone else corroborate this

If so, is there a known workaround to allow UseItemStyleForSubItems = False (i.e., independent style properties for all subitems), but avoid the nasty "screen flicker?

On a side note, the VB6 version of the ListView control (exposed through mscomctl.ocx, If I recall) did not expose a UseItemStyleForSubItems Property. However, the VB6 version behaved as though it were set to UseItemStyleForSubItems = False (i.e., each subitem's style properties could be set independently) and yet the VB6 control did not introduce the same degree of "screen flicker.

It seems the ListView control available via the .Net Framework is flawed in this respect. Can anyone shed some light
 
P

Patrick Steele [MVP]

Through testing, I believe I've proven that setting
UseItemStyleForSubItems = False on ListView controls introduces
"screen flicker" whenever items/subitems are added or modified
in a ListView. The "screen flicker" problem disappears when
UseItemStyleForSubItems is set to True (the default setting).

If you've got a number of changes to make try the "SuspendLayout" and
"ResumeLayout" methods on the ListView.
 
C

Claes Bergefall

How it works:
The ListView control in .NET uses CustomDraw (i.e. handles the NM_CUSTOMDRAW
notification) to draw the items and subitems when you set
UseItemStyleForSubItems = False. I suspect that the ListView control in VB6
does the same.

Why it flickers:
..NET uses GDI+ to draw things. GDI+ is still in its first version and it
does not yet support hardware acceleration, so it's performance is not that
good.
VB6 uses GDI to draw things. GDI has been around for quite a while, is
highly optimized and supports hardware acceleration, so it's performance is
excellent.



/claes



mhetherington said:
Through testing, I believe I've proven that setting
UseItemStyleForSubItems = False on ListView controls introduces "screen
flicker" whenever items/subitems are added or modified in a ListView. The
"screen flicker" problem disappears when UseItemStyleForSubItems is set to
True (the default setting).
Can anyone else corroborate this?

If so, is there a known workaround to allow UseItemStyleForSubItems =
False (i.e., independent style properties for all subitems), but avoid the
nasty "screen flicker?"
On a side note, the VB6 version of the ListView control (exposed through
mscomctl.ocx, If I recall) did not expose a UseItemStyleForSubItems
Property. However, the VB6 version behaved as though it were set to
UseItemStyleForSubItems = False (i.e., each subitem's style properties could
be set independently) and yet the VB6 control did not introduce the same
degree of "screen flicker."
It seems the ListView control available via the .Net Framework is flawed
in this respect. Can anyone shed some light?
 
G

Guest

Patrick

Thanks for the advice. Unfortunately, SuspendLayout/ResumeLayout does no better than BeginUpdate/EndUpdate, which doesn't seem to do anything at all to improve the flicker

I even tried EndUpdate/BeginUpdate and SuspenLayout/ResumeLayout together and that didn't help either

Any other ideas

----- Patrick Steele [MVP] wrote: ----

Through testing, I believe I've proven that setting
UseItemStyleForSubItems = False on ListView controls introduces
"screen flicker" whenever items/subitems are added or modified
in a ListView. The "screen flicker" problem disappears when
UseItemStyleForSubItems is set to True (the default setting)

If you've got a number of changes to make try the "SuspendLayout" and
"ResumeLayout" methods on the ListView
 
G

Guest

Claes

Thanks for the explanation, but I don't see how it fits in this case. Let me add more detail and perhaps you or someone else can connect the dots for me (everything below assumes VB.Net)

Initial Setup: Drop a ListView onto a Windows Form. Change the View Property to Details. Set the GridLines Property to False. Add a handful of Columns to the ListView (the more you add, the more obvious the flicker will be, but it should be pretty obvious with as few as 5 Columns). Now, try adding and manipulating ListViewItems and ListViewSubItems in the following ways

Scenario #1a: Populate the ListView with a couple ListViewItems to start with. Set a Timer to change the Text Property of a few ListViewSubItems every 5 seconds or so (perform an incremental count , or something, and update the items to something obviously different). You should notice almost no flicker (maybe once in every 10+ timer events)

Scenario #2a: Do the same as in Scenario #1a, but wrap your 5-sec changes in a BeginUpdate/EndUpdate block. Flicker should be on par with that of Scenario #1a (i.e., it doesn't seem to help, but it also doesn't seem to hurt)

Scenario #3a: Do the same as Scenario #2a, but don't actually modify any subitems on your 5-sec timer events. In other words, issue a BeginUpdate followed immediately by an EndUpdate (without doing anything in-between). You should see absolutely no flicker whatsoever (expected, right?...Wait until Scenario #3b)

Scenario #1b: Same as Scenario #1a, but set the UseItemStyleForSubItems = False on each ListViewItem you add to the ListView. You should observe flicker on all but a (maybe) few passes of the 5-second timer event – there should certainly be more flicker than any of the 3 previous scenarios)

Scenario #2b: Same as Scenario #1b, but wrap your 5-sec changes in a BeginUpdate/EndUpdate block. Again, flicker occurs on nearly every pass of the timer event

Scenario #3b: Same as Scenario #2b, but don't actually modify any subitems on your 5-sec timer events. In other words, issue a BeginUpdate followed immediately by an EndUpdate (without doing anything in-between). Unexpectedly, you'll note flicker on nearly every pass of the timer. But why?!?!? Nothing has changed in the ListView - no text, no styles, no nothing! I would have expected the results to be similar to those in Scenario #3a

So, while your point about differences in GDI+ not supporting hardware acceleration may be entirely accurate, I'm still left wondering why GDI+ has anything to do with explaining this particular phenomenon (i.e., the difference in behavior between Scenarios #3a and #3b). No messages to repaint/redraw should be sent whatsoever to the graphics subsystem, because nothing has changed

In my mind (without knowing any of the gory details of GDI+), the problem seems to lie more in the design of the .Net ListView control. Specifically, that it is designed "well enough" NOT to send any redraw/repaint messages with UseItemStyleForSubItems = True (the default) when no changes are made to the ListView. But, it's as if the control is sending repaint/redraw messages each and every time EndUpdate is called with UseItemStyleForSubItems = True, whether items/subitems have actually changed or not (i.e., poor design of the control)

If this is not the case, can you or anyone explain this in a way to clearly pinpoint GDI+ as the problem and not the control itself? In other words, isn’t it still up to the control itself to issue the redraw/repaint messages? Thanks


----- Claes Bergefall wrote: ----

How it works
The ListView control in .NET uses CustomDraw (i.e. handles the NM_CUSTOMDRA
notification) to draw the items and subitems when you se
UseItemStyleForSubItems = False. I suspect that the ListView control in VB
does the same

Why it flickers
..NET uses GDI+ to draw things. GDI+ is still in its first version and i
does not yet support hardware acceleration, so it's performance is not tha
good
VB6 uses GDI to draw things. GDI has been around for quite a while, i
highly optimized and supports hardware acceleration, so it's performance is
excellent.



/claes



mhetherington said:
Through testing, I believe I've proven that setting
UseItemStyleForSubItems = False on ListView controls introduces "screen
flicker" whenever items/subitems are added or modified in a ListView. The
"screen flicker" problem disappears when UseItemStyleForSubItems is set to
True (the default setting).False (i.e., independent style properties for all subitems), but avoid the
nasty "screen flicker?"mscomctl.ocx, If I recall) did not expose a UseItemStyleForSubItems
Property. However, the VB6 version behaved as though it were set to
UseItemStyleForSubItems = False (i.e., each subitem's style properties could
be set independently) and yet the VB6 control did not introduce the same
degree of "screen flicker."in this respect. Can anyone shed some light?
 
C

Claes Bergefall

First of, EndUpdate invalidates (i.e. redraws) the entire client area. It
doesn't matter if you changed anything or not, or what propertyvalues you're
using. BeginUpdate/EndUpdate isn't some universal solution that should
always be called. If you're not updating anything then don't use them! IMO
there is nothing wrong with this design

Scenario 1a, 2a, 3a: UseItemStyleForSubItems = True
The ListView and its content is drawn by Windows (inside the common control
libraries)
Windows uses GDI (same as VB6) => Quick and flicker free

Scenario 1b, 2b, 3b: UseItemStyleForSubItems = False
The ListView and its content is drawn by .NET (inside the framework)
..NET uses GDI+ => Slow and with flicker

Unfortunately you'll have to live with the flicker until the next version of
GDI+ is released. It is supposed to have support for hardware acceleration,
but AFAIK no official release date has been announced

/claes


mhetherington said:
Claes,

Thanks for the explanation, but I don't see how it fits in this case. Let
me add more detail and perhaps you or someone else can connect the dots for
me (everything below assumes VB.Net).
Initial Setup: Drop a ListView onto a Windows Form. Change the View
Property to Details. Set the GridLines Property to False. Add a handful of
Columns to the ListView (the more you add, the more obvious the flicker will
be, but it should be pretty obvious with as few as 5 Columns). Now, try
adding and manipulating ListViewItems and ListViewSubItems in the following
ways:
Scenario #1a: Populate the ListView with a couple ListViewItems to start
with. Set a Timer to change the Text Property of a few ListViewSubItems
every 5 seconds or so (perform an incremental count , or something, and
update the items to something obviously different). You should notice
almost no flicker (maybe once in every 10+ timer events).
Scenario #2a: Do the same as in Scenario #1a, but wrap your 5-sec changes
in a BeginUpdate/EndUpdate block. Flicker should be on par with that of
Scenario #1a (i.e., it doesn't seem to help, but it also doesn't seem to
hurt).
Scenario #3a: Do the same as Scenario #2a, but don't actually modify any
subitems on your 5-sec timer events. In other words, issue a BeginUpdate
followed immediately by an EndUpdate (without doing anything in-between).
You should see absolutely no flicker whatsoever (expected, right?...Wait
until Scenario #3b).
Scenario #1b: Same as Scenario #1a, but set the UseItemStyleForSubItems =
False on each ListViewItem you add to the ListView. You should observe
flicker on all but a (maybe) few passes of the 5-second timer event - there
should certainly be more flicker than any of the 3 previous scenarios).
Scenario #2b: Same as Scenario #1b, but wrap your 5-sec changes in a
BeginUpdate/EndUpdate block. Again, flicker occurs on nearly every pass of
the timer event.
Scenario #3b: Same as Scenario #2b, but don't actually modify any
subitems on your 5-sec timer events. In other words, issue a BeginUpdate
followed immediately by an EndUpdate (without doing anything in-between).
Unexpectedly, you'll note flicker on nearly every pass of the timer. But
why?!?!? Nothing has changed in the ListView - no text, no styles, no
nothing! I would have expected the results to be similar to those in
Scenario #3a.
So, while your point about differences in GDI+ not supporting hardware
acceleration may be entirely accurate, I'm still left wondering why GDI+ has
anything to do with explaining this particular phenomenon (i.e., the
difference in behavior between Scenarios #3a and #3b). No messages to
repaint/redraw should be sent whatsoever to the graphics subsystem, because
nothing has changed.
In my mind (without knowing any of the gory details of GDI+), the problem
seems to lie more in the design of the .Net ListView control. Specifically,
that it is designed "well enough" NOT to send any redraw/repaint messages
with UseItemStyleForSubItems = True (the default) when no changes are made
to the ListView. But, it's as if the control is sending repaint/redraw
messages each and every time EndUpdate is called with
UseItemStyleForSubItems = True, whether items/subitems have actually changed
or not (i.e., poor design of the control).
If this is not the case, can you or anyone explain this in a way to
clearly pinpoint GDI+ as the problem and not the control itself? In other
words, isn't it still up to the control itself to issue the redraw/repaint
messages? Thanks.
 
C

Claes Bergefall

You won't find a reference that says exactly that :). You'll have to put
two and two together

Part one:
I'm pretty sure that you can find the following info in MSDN somewhere:
- .NET uses GDI+ for its drawing operations
- Win32 uses GDI for its drawing operations
Unfortunately I don't know exactly where that info is and MSDN is quite
large so you'll have to dig yourself (or you'll have to trust me :))

Part two:
..NET uses custom draw (i.e. handles NM_CUSTOMDRAW) and draws the items
itself when your set UseItemStyleForSubItems = False.
I stumbled upon that one by mistake. I needed to handle the NM_CUSTOMDRAW
notification myself, and in doing so noticed that the sub item styles
stopped working! Every item and subitem was black, not red or blue or
whatever I had assigned to them. Removing my own handling of NM_CUSTOMDRAW
made the items and subitems to appear in color again. If I didn't use
separate styles for the subitems my custom drawing code didn't cause any
problems . So my conclusion was that .NET uses custom draw to draw the
subitems if you have separate styles for the them. A look at the source code
using Reflector* confirmed that conclusion.

So, if you put one and two together you get:
UseItemStyleForSubItems = False = GDI+
UseItemStyleForSubItems = True = GDI

*Reflector is a really good decompiler for .NET. I recomend that you
download it (http://www.aisto.com/roeder/dotnet/)

/claes

mhetherington said:
Thanks for the clarification, Claes.

Where can I find documentation that describes the (UseItemStyleForSubItems
= True = GDI) and (UseItemStyleForSubItems = False = GDI+) difference you
describe (i.e., what is your reference)? I'd like to better understand the
details of the .NET ListView.
 
C

Claes Bergefall

That is a fair question, but I'm afraid that only MS will be able to answer
it. They made the decision to use GDI+ in .NET

Personally I think that was a good decision. GDI+ seems to be easier to work
with than GDI. The bad decision was to skip support for hardware
acceleration in the first version of GDI+.

Just hang in there. It will be better in the future :)

/claes

mhetherington said:
Claes,

Thanks. I really appreciate the follow-ups and insight.

So, I trust your explanation based on the anecdotal "evidence" you
supplied. Without knowing the specific details, it was my hunch from the
beginning that the drawing/painting methods were different when
UseItemStyleForSubItems = True vs. when UseItemStyleForSubItems = False.
You seem to identify that it's GDI vs. GDI+ which explains that difference.
However, I'm still left scratching my head as to why MS would implement
the control this way? From what you (and others on different threads) have
stated, GDI+ doesn't yet perform as well in all areas as GDI. In this case
specifically, GDI+ doesn't/can't utilize hardware acceleration for video,
thus introducing the flicker phenomenon many people seem to be battling with
..NET controls.
Additionally, as you also suggested, the VB6 ListView Control behaves
similar to the .NET ListView control set with UseItemStyleForSubItems =
False. Thus, if VB6ListView (+ implicit UseItemStyleForSubItems = False) =
GDI = NoFlicker, why would MS modify the .NET ListView control in such a way
that .NETListView (+ explicit UseItemStyleForSubItems = False) = GDI+ =
Flicker?
In other words, why not leave the control using GDI only, as it was in VB6
(especially since introducing GDI+ negatively impacts the control with
regards to flicker)? Is that a fair question, or am I still missing
something?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top