Trouble with the ListView SelectedIndexChanged event
- Monday, October 08, 2007
I've been messing with a System.Windows.Forms.ListView control lately. I have a list of items in a standard ListView control. If the user selects an item, I have some other controls to be shown. If the user deselects the item in the ListView I want these other controls to be hidden.
Now, whenever a user changes the selected item in the ListView control, the SelectedIndexChanged event is called twice: once for deselecting the item (SelectedItems.Count == 0) and once for selecting the new item. This causes the "other controls" to flicker: they first get hidden, then show up again.
Despite some existing solutions using a Timer (here) I analyzed the available events of a ListView. Click and MouseClick are useless since they only occur when the user clicks an item, not when deselecting. MouseUp looks promising since it also fires when the user clicked somewhere outside the items. I have not found a key stroke to deselect an item in a ListView, so MouseUp should be sufficient to check for deselection.
Using that I create a new ListViewEx derived from ListView with two need events: ItemsDeselected and ItemSelected. The originally SelectedIndexChanged event is left untouched.
Feel free to use that code.
Now, whenever a user changes the selected item in the ListView control, the SelectedIndexChanged event is called twice: once for deselecting the item (SelectedItems.Count == 0) and once for selecting the new item. This causes the "other controls" to flicker: they first get hidden, then show up again.
Despite some existing solutions using a Timer (here) I analyzed the available events of a ListView. Click and MouseClick are useless since they only occur when the user clicks an item, not when deselecting. MouseUp looks promising since it also fires when the user clicked somewhere outside the items. I have not found a key stroke to deselect an item in a ListView, so MouseUp should be sufficient to check for deselection.
Using that I create a new ListViewEx derived from ListView with two need events: ItemsDeselected and ItemSelected. The originally SelectedIndexChanged event is left untouched.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
namespace Instyler.Controls
{
class ListViewEx : ListView
{
private bool _enableDeselectionEvent = false;
protected override void OnSelectedIndexChanged( EventArgs e )
{
_enableDeselectionEvent = ( SelectedItems.Count == 0 );
if ( SelectedItems.Count != 0 )
OnItemSelected( this, new EventArgs() );
base.OnSelectedIndexChanged( e );
}
protected override void OnMouseUp( MouseEventArgs e )
{
if(_enableDeselectionEvent)
OnItemsDeselected( this, new EventArgs() );
base.OnMouseUp( e );
}
#region Our new events
public delegate void ItemsDeselectedHandler( object sender, EventArgs e );
[Description("Event raised when items got deselected"), Category("Behavior")]
public event ItemsDeselectedHandler ItemsDeselected = null;
protected virtual void OnItemsDeselected( object sender, EventArgs e )
{
if ( ItemsDeselected != null )
ItemsDeselected( sender, e );
}
public delegate void ItemSelectedHandler( object sender, EventArgs e );
[Description("Event raised when a new item got selected."), Category("Behavior")]
public event ItemSelectedHandler ItemSelected = null;
protected virtual void OnItemSelected( object sender, EventArgs e )
{
if ( ItemSelected != null )
ItemSelected( sender, e );
}
#endregion
}
}
Feel free to use that code.
Labels: Coding