WPF: Non-selectable ListBoxItem and ListViewItem


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. #1 by Anonymous on August 26, 2014 - 10:14 pm

    So how would you use this with a datatemplate ?

  2. #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. #3 by Gqqnbig on December 18, 2012 - 1:31 am

    Very interesting and it may help me.

  1. ListBox as Toolbar | eagleboost's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: