Resetting the Selected Item of a Silverlight 2 ListBox Control
Silverlight version: 2.0.31005.0
If you are trying to reset the selected item of a ListBox control using either the SelectedItem or SelectedIndex properties, it will not work with the version of Silverlight stated above. From what I can glean in the Silverlight forums, this method did at one time work (previous release candidate maybe) and is also a known issue that is being addressed (for the current version).
In the meantime, you can adapt your application to use another existing control or custom control, or you could do something like the following:
Option 0: Reset the selected item or index outside of your SelectionChanged event handler. One way to do this is to use a DispatcherTimer. When the ListBox SelectionChanged event fires, start the timer. In the Tick handler, stop the timer and perform the reset (set SelectedItem to null or SelectedIndex to -1).
Drawbacks: this isn’t unexpected, but resetting the selected item is reflected by the ListBox UI, so the last selected ListBox item may not be as noticeable to the user. If you want to show the last selected item AND enable clicking on the same item multiple times in sequence, then see the option below.
Option 1: You can also reset the selected item without resorting to the use of an additional timer. Simply take advantage of the Dispatcher.BeginInvoke method like in the following code ('lb' refers to a ListBox instance):
Dispatcher.BeginInvoke(new Action(delegate() { lb.SelectedItem = null; }));
OR
Dispatcher.BeginInvoke(() => { lb.SelectedItem = null; });
Option 2: Create a custom list box class that inherits from ListBox – let’s call it CustomListBox. Override the GetContainerForItemOverride method to return a custom list box item class (CustomListBoxItem) rather than the default ListBoxItem instance. Create a new public event called CustomSelectionChanged which will serve as the replacement for SelectionChanged.
public class CustomListBox : ListBox
{
//fired every time a list box item is clicked
public event SelectionChangedEventHandler CustomSelectionChanged;
protected override DependencyObject GetContainerForItemOverride()
{
CustomListBoxItem item = new CustomListBoxItem(this);
if (base.ItemContainerStyle != null)
{
item.Style = base.ItemContainerStyle;
}
return item;
}
public void OnCustomSelectionChanged(CustomListBoxItem item)
{
List<CustomListBoxItem> addedItems =
new List<CustomListBoxItem>();
addedItems.Add(item);
SelectionChangedEventHandler handler = CustomSelectionChanged;
if (handler != null)
{
handler(this, new SelectionChangedEventArgs(
new List<CustomListBoxItem>(), addedItems));
}
}
}
In CustomListBoxItem, which should inherit from ListBoxItem, create a constructor that takes a CustomListBox instance as a parameter and stores is for later use. Finally, override the OnMouseLeftButtonDown method and fire the CustomSelectionChanged event of the containing CustomListBox.
public class CustomListBoxItem : ListBoxItem
{
CustomListBox _customListBoxContainer;
// Needed to avoid error in case of instantiation in XAML. If
// CustomListBoxItems are added in XAML directly,
// CustomListBox will act like a normal ListBox and only allow
// each item to be selected once.
public CustomListBoxItem()
{ }
public CustomListBoxItem(CustomListBox customListBox)
{
this._customListBoxContainer = customListBox;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (this._customListBoxContainer != null)
{
this._customListBoxContainer.OnCustomSelectionChanged(this);
}
}
}
Download example: ResetListBoxExample.zip
11/18/2008 12:13:25 PM (Pacific Standard Time, UTC-08:00)
Shrewd Programming