c# ListView selection change

J

Jure Bogataj

Hi all!

I have a problem (performance issue) with listview. I have implemented an
ItemSelectionChange on my listview and put some code in it (I build some
toolbar based on selection and update info in statusbar). When selecting one
item (clicking on listview) it works fast, without noticing. However if
selecting multiple items with SHIFT (approx. 500 items) or selecting with
mouse, for each item selected through all listview an event
(ItemSelectionChange) gets called. And this is what slows down my app (the
code running 500 times instead of one time - OnSelectionEnd or sth.). Is it
possible to have an event or simulate it only when selection is finished
(e.g. when all 500 items are selected) not for each and every one?

Thanks in advance!

Best regards,
Jure
 
P

Peter Duniho

Jure said:
[...] However if
selecting multiple items with SHIFT (approx. 500 items) or selecting with
mouse, for each item selected through all listview an event
(ItemSelectionChange) gets called. And this is what slows down my app (the
code running 500 times instead of one time - OnSelectionEnd or sth.). Is it
possible to have an event or simulate it only when selection is finished
(e.g. when all 500 items are selected) not for each and every one?

I'm not sure, not having run into this particular problem myself.
However, here's a thought: in the same class with the event handler,
include a boolean variable indicating whether or not a selection-changed
event is being handled.

Then, the first thing you do is check the flag. If it's set, you do
nothing. If it's not set, you set it and use BeginInvoke() with a
method that should do the actual selection-changed handling.

Then in that method, the one that does the actual selection-changed
handling, you clear the flag again. As well as do whatever handling it
is you want to do, of course.

This will ensure that no new handling is done until you've had a chance
to process the current selection-changed event. The handling won't be
done inline with the user-interaction, and any user input that happens
before you have that chance will not cause a new attempt to handle the
event.

Whether this will actually address your concern, I'm not sure. Your
post isn't very clear about the specific user action or actions that
you're trying to deal with, nor is it clear why your event handling is
so costly that it causes a noticeable delay.

If the above isn't helpful, you should consider being more specific
about your question. This would include posting a concise-but-complete
sample of code that reliably demonstrates the issue. You will also want
to post very specific instructions for how to use the code, since
apparently user behavior is important in the issue.

Pete
 
L

Liz

Jure Bogataj said:
Hi all!

I have a problem (performance issue) with listview. I have implemented an
ItemSelectionChange on my listview and put some code in it (I build some
toolbar based on selection and update info in statusbar). When selecting
one item (clicking on listview) it works fast, without noticing. However
if selecting multiple items with SHIFT (approx. 500 items) or selecting
with mouse, for each item selected through all listview an event
(ItemSelectionChange) gets called. And this is what slows down my app (the
code running 500 times instead of one time - OnSelectionEnd or sth.). Is
it possible to have an event or simulate it only when selection is
finished (e.g. when all 500 items are selected) not for each and every
one?

Peter's already given you an approach to that but ... how does the program
"know" that "selection is finished" ?

I don't have any problem handling the event and doing something simple with
it (displaying the number of items selected on a Label, for example); if
your handler is complex, perhaps you can defer the action taken in your
handler until the user does *something else* ... e.g.: user selects item 2,
item 17, item 10 and then clicks an "Act on Selection(s)" button ... of
course in that case you don't need to use the ItemSelectionChange event at
all

If you don't want user intervention perhaps you could check the value of
ListView.SelectedIndeces every N seconds (not my own favorite idea)

L
 
M

Matt Brunell

Jure Bogataj said:
Hi all!

I have a problem (performance issue) with listview. I have implemented an
ItemSelectionChange on my listview and put some code in it (I build some
toolbar based on selection and update info in statusbar). When selecting
one item (clicking on listview) it works fast, without noticing. However
if selecting multiple items with SHIFT (approx. 500 items) or selecting
with mouse, for each item selected through all listview an event
(ItemSelectionChange) gets called. And this is what slows down my app (the
code running 500 times instead of one time - OnSelectionEnd or sth.). Is
it possible to have an event or simulate it only when selection is
finished (e.g. when all 500 items are selected) not for each and every
one?

Thanks in advance!

Best regards,
Jure

Hi Jure,

It is possible to create a new event like that, and handle it, but it would
be extremely difficult. You would have to track down all of the windows
messages that could potentially cause a selection change, and manage them.
There's a lot of behavior managing the selection of items in the listview.
For example, you can move the focus rectangle while holding the 'Ctrl' key,
and then select individual items with the spacebar.

A better way perhaps for you would be to put a minimal delay in your
ItemSelectionChange Handler. Say -- 50ms. Use a timer, Once the selection
changes, restart the timer. If the selection changed more than once within
the delay period, then the original is ignored, but after the delay has
expired, the logic is executed.

Like this:

public class SelectionEndListView : ListView
{
private System.Windows.Forms.Timer m_timer;
private const int SELECTION_DELAY = 50;

public SelectionEndListView()
{
m_timer = new Timer();
m_timer.Interval = SELECTION_DELAY;
m_timer.Tick += new EventHandler(m_timer_Tick);
}

protected override void OnSelectedIndexChanged(EventArgs e)
{
base.OnSelectedIndexChanged(e);

// restart delay timer
m_timer.Stop();
m_timer.Start();
}

private void m_timer_Tick(object sender, EventArgs e)
{
m_timer.Stop();

// Perform selection end logic.
Console.WriteLine("Selection Has Ended");
}
}

-- Matt
 
J

Jure Bogataj

Thank you all for your replies. I will try to implement this with timer. I
think 50ms is not too long for user to notice that toolbar doesn't get
changed immediately.
Thanks again!

Best regards,
Jure
 
J

Jure Bogataj

Thank you! Works very well with timer. A lot faster than before.

Best regards,
Jure
 

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