Problem
Sometimes in WPF you want to have a list of items contained in a ListBox (or ListView) that you don’t want to be selectable. You could set those items to be disabled, by assigning IsEnabled to False, but that may interfere with styles among other things. You could also (probably the best idea) use a ItemsControl, from which the ListBox derives, that doesn’t include selectable-items functionality. However, for whatever reason, you may just want to use a ListBox (or ListView) instead.
Solution
NOTE: The code below is for use with a ListBox/ListBoxItem; to use it for a ListView/ListViewItem just do a find-and-replace, the implementation logic is the same.
Class: ListBoxItemAPs (ListBoxItemAttachedProperties)
public static class ListBoxItemAttachedProperties { #region IsSelectableProperty public static readonly DependencyProperty IsSelectableProperty = DependencyProperty.RegisterAttached("IsSelectable", typeof(bool), typeof(ListBoxItemAttachedProperties), new UIPropertyMetadata(true, IsSelectableChanged)); public static bool GetIsSelectable(ListBoxItem obj) { return (bool)obj.GetValue(IsSelectableProperty); } public static void SetIsSelectable(ListBoxItem obj, bool value) { obj.SetValue(IsSelectableProperty, value); } private static void IsSelectableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ListBoxItem item = d as ListBoxItem; if (item == null) return; if ((bool)e.NewValue == false && (bool)e.OldValue == true) { item.Selected -= new RoutedEventHandler(item_Selected); item.Selected += new RoutedEventHandler(item_Selected); BindingOperations.ClearBinding(item, ListBoxItem.IsSelectedProperty); if (item.IsSelected) item.IsSelected = false; } else if ((bool)e.NewValue == true && (bool)e.OldValue == false) item.Selected -= new RoutedEventHandler(item_Selected); } private static void item_Selected(object sender, RoutedEventArgs e) { ListBoxItem item = sender as ListBoxItem; if (item == null) return; item.IsSelected = false; } #endregion IsSelectableProperty }
XAML: Example Usage of ListBoxItemAPs.IsSelectable
<Style x:Key="NonSelectableListBoxItemStyle" TargetType="{x:Type ListBoxItem}"> <Setter Property="local:ListBoxItemAttachedProperties.IsSelectable" Value="False" /> </Style> <!-- Only the 2nd item will be non-selectable --> <ListBox> <ListBoxItem Content="Item1" /> <ListBoxItem local:ListBoxItemAttachedProperties.IsSelectable="False" Content="Item2" /> <ListBoxItem Content="Item3" /> </ListBox> <!-- All items will be non-selectable --> <ListBox ItemContainerStyle="{StaticResource NonSelectableListBoxItemStyle}"> <ListBoxItem Content="Item1" /> <ListBoxItem Content="Item2" /> <ListBoxItem Content="Item3" /> </ListBox>
#1 by Anonymous on August 26, 2014 - 10:14 pm
So how would you use this with a datatemplate ?
#2 by Daniël on April 9, 2013 - 6:20 am
I needed to add ‘e.Handled = true;’ in static method ‘item_Selected’ for this to work.
#3 by Gqqnbig on December 18, 2012 - 1:31 am
Very interesting and it may help me.