This article is compatible with the latest version of Silverlight.
Introduction
The need of selection is a pretty common thing. That made us think of a way to generalize the task and create a reusable class that can be used in more than one scenario. We put together a simple helper class that lets you handle selection easily. The responsibilities of the class are:
- to keep only one item selected;
- to give you the index of the selected item;
- possibly to return a handle to the selected item
You can use the SelectionManager on any ObservableCollection of ISelectable objects. In fact you could use it on non-UI objects if you need to have one object in one state and the rest in another. ISelecatble is a simple interface that has three parts:
- Selected event that should be raised when an object transits to the Selected state
- Select/Deselect methods that should set the state of the object to selected or deselected
|
public interface ISelectable
{
event EventHandler Selected;
void Select();
void Deselect();
}
|
|
After you define these three parts in your class you only need to pass the collection of objects to the SelectionManager and hook to the SelectionChange event.
Items are selected on MouseOver.
Download source code.
Implementation
The SelectionManager keeps a reference to an ObservableCollection outside the class and it hooks to the Selected event of each item provided by ISelectable.
private ObservableCollection items;
public void HookToObservableCollection( ObservableCollection items )
{ ...
this.items = items;
items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(
CollectionChanged );
foreach ( ISelectable current in this.items )
{
current.Selected += new EventHandler( OnItemSelected );
}
}
The SelectionManager handles changes in the collection automatically.
void CollectionChanged( object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e )
{
if ( e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Replace )
{
foreach ( ISelectable newItem in e.OldItems )
{
newItem.Selected -= new EventHandler( OnItemSelected );
}
}
if ( e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace )
foreach ( ISelectable newItem in e.NewItems )
{
newItem.Selected += new EventHandler( OnItemSelected );
}
}
When an item is selected the SelectionManager deselects the last selected item. and fires the SelectionChange event.
public void OnItemSelected( object sender, EventArgs e )
{
_next = this.items.IndexOf( sender as ISelectable );
if ( _lastSelected != _next )
this.items[ _lastSelected ].Deselect();
_lastSelected = _next;
if ( this.SelectionChange != null )
this.SelectionChange( sender, new SelectionChangedEventArgs( _lastSelected ) );
}
To deliver the index of the selected item SelectionChange uses SelectionChangedEventArgs that contain an int.
public class SelectionChangedEventArgs : EventArgs
{
public SelectionChangedEventArgs( int indexOfSelectedItem )
{
this.selectedItemIndex = indexOfSelectedItem;
}
public int selectedItemIndex;
}
Conclusion
In our example we demonstrate the selection in two ways. Inside the ISelectable control with the blue border and outside in the application with the grey "x"-box. Check out our source for more details.