Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET ListView: event after changing selection

On the ListView control, I need an event to fire after the selection changes, but only once per user action. If I simply use the SelectedIndexChanged, that event fires twice in most cases (once when the previous element is unselected and once more when the new element is selected) event if the user only clicked on the control once.

The two events fire quickly one after the other, but the computation I do when the selection changes takes time (almost a second) so it is done twice and slows down the interface.

What I want to do is only do it once per user action (doing it before the new element is selected is useless) but I have no way of knowing if the event is just the first of a pair (in order to skip the first computation) because if the user just deselected the selected element, it will fire only once.

I can't use the Click or MouseClick events because those don't fire at all if the user clicked outside the list to remove the selection.

Thanks for your help.

like image 705
Laurent Avatar asked Jul 28 '09 04:07

Laurent


3 Answers

Here's my solution in VB.NET, using the technique described in ObjectListView as suggested by Grammarian:

Private idleHandlerSet As Boolean = False

Private Sub listview1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listview1.SelectedIndexChanged
    '' may fire more than once
    If Not idleHandlerSet Then
        idleHandlerSet = True
        AddHandler Application.Idle, New EventHandler(AddressOf listview1_SelectionChanged)
    End If
End Sub

Private Sub listview1_SelectionChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '' will only fire once
    idleHandlerSet = False
    RemoveHandler Application.Idle, New EventHandler(AddressOf listview1_SelectionChanged)
    DoSearch()
End Sub
like image 84
Laurent Avatar answered Nov 11 '22 13:11

Laurent


I found this annoying too, so in ObjectListView (an open source wrapper around .NET WinForms ListView) there is a SelectionChanged event, which only happens once per user action.

With a straight .NET ListView, when any item's selection state changes, it triggers a SelectedIndexChanged event. So, for simple click on another row, you get one event for deselecting the previously selected row, and another for selecting the new one.

If you have one hundred rows selected, and selected a different row, you are going to get 101 SelectedIndexChanged events -- which can be a royal pain.

Anyway, with an ObjectListView, you only get one SelectionChanged event regardless of how many rows were selected or deselected.

like image 23
Grammarian Avatar answered Nov 11 '22 12:11

Grammarian


I had the same issue as OP in a C# WinForms project using ListViews, and Laurent's answer was exactly what I was looking for. The code below is Laurent's answer translated into C#:

private bool IdleHandlerSet { get; set; }

private void ListView_SelectedIndexChanged(object sender, EventArgs e)
{
    // this will fire every time items are selected or deselected.
    if (!IdleHandlerSet)
    {
        IdleHandlerSet = true;
        Application.Idle += ListView_SelectionChanged;
    }
}

private void ListView_SelectionChanged(object sender, EventArgs e)
{
    // this will only fire once only
    IdleHandlerSet = false;
    Application.Idle -= ListView_SelectionChanged;

    DoStuff();
}
like image 1
ubercam Avatar answered Nov 11 '22 11:11

ubercam