C# ListView - Detecting when the user deselects an item or select a new one

1.4k Views Asked by At

I'm trying to detect when the user selects a new item in a ListView and when he deselects everything (by clicking on an empty area on the ListView), but I'm having a hard time getting it right. I need this to enable or disable a couple of "Move item up" and "Move item down" buttons. I think the best way to do this is to handle the ItemSelectionChanged event, so I have this, which seems pretty obvious:

private void lstItems_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) {
    if (e.IsSelected) {
        cmbMoveUp.Enabled = true;
        cmbMoveDn.Enabled = true;
    } else {
        cmbMoveUp.Enabled = false;
        cmbMoveDn.Enabled = false;
    }
}

It works fine when the user deselects everything, but the problem is that this event is fired twice when the user selects another item: one time for deselecting the current item and another for selecting the new one. This causes some blinking on the "Move item up" and "Move item down" buttons, because it will first disable the buttons (because the current item was deselected) and then enable them again (when the new item is selected).

Anyone knows how can I solve this issue? I've ran out of ideas.

Thanks in advance.

4

There are 4 best solutions below

3
On

I never used listView, but I think you can remove else part of lstItems_ItemSelectionChanged method, then in if part you can first disable all buttons and then enale just two related buttons. lstItems_ItemSelectionChanged event fires two time, first time "if" does'nt fire and second time "if" will fire. so your problem will be solved.

1
On

Have you tried using lstItems_SelectedIndexChanged instead of lstItems_ItemSelectionChanged? I believe that would only trigger this 1 time. Hope that helps!

0
On

I wanted my list view to disable two buttons when the list was de-selected. The following code achieved this.

private void Session_List_SelectedIndexChanged(object sender, EventArgs e) {
    bool toggle = true;
    if (Session_List.SelectedItems.Count == 0) {
        toggle = false;
    }

    Selected_Task.Enabled = toggle;   
    Perform_Task.Enabled = toggle;
}
0
On

The best solution I've found is to temporarily set an event handler to Application.Idle and do your checking from there, like so:

bool handled;
private void lstItems_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) {
    if (!handled)
    {   handled = true;
        Application.Idle += SelectionChangeDone;   }
}

private void SelectionChangeDone(object sender, EventArgs e) {
    Application.Idle -= SelectionChangeDone;
    handled = false;

    if (lstItems.SelectedItems.Count > 0)
         cmbMoveUp.Enabled = cmbMoveDn.Enabled = true;
    else cmbMoveUp.Enabled = cmbMoveDn.Enabled = false;
}

It shouldn't matter whether you use ItemSelectionChanged or SelectedIndexChanged. Both will work fine in this case.

Big thanks goes to Grammarian for his answer to essentially the same question here: https://stackoverflow.com/a/26393234/2532220