tags:

views:

1820

answers:

2

I have a simple listbox with extended selection mode. Selection works almost perfectly fine like it works in explorer. But deselection doesn't really work all that well. What I want is that when I click on something outside the range of elements in the listbox I want all elements to be deselected. I doesn't seem to behave that way by default and I did a dirty hack involving selectionchanged and mouseup to hack it up. But there has to be a better way. Any ideas?

+1  A: 

It isn't that dirty to add in the deselection functionality, and you're on the right track. The main issue is that by default the ListBoxItems inside the ListBox will stretch all the way across, making it pretty tough to not click on one.

Here's an example ListBox that modifies the default ItemContainerStyle so that the items just take up the left side of the list and there is some spacing between the items as well.

<ListBox SelectionMode="Extended"
   Width="200" Mouse.MouseDown="ListBox_MouseDown">
 <ListBox.ItemContainerStyle>
  <Style TargetType="{x:Type ListBoxItem}">
   <Setter Property="Background"
     Value="LightBlue" />
   <Setter Property="Margin"
     Value="2" />
   <Setter Property="Padding"
     Value="2" />
   <Setter Property="Width"
     Value="100" />
   <Setter Property="HorizontalAlignment"
     Value="Left" />
  </Style>
 </ListBox.ItemContainerStyle>
 <ListBoxItem >Item 1</ListBoxItem>
 <ListBoxItem >Item 2</ListBoxItem>
 <ListBoxItem >Item 3</ListBoxItem>
 <ListBoxItem >Item 4</ListBoxItem>
</ListBox>

To deselect the selected items we just need to set the SelectedItem to null in the EventHandler. When we click on a ListBoxItem, it will handle the MouseDown/Click etc to set the SelectedItem or modify the SelectedItems. Because of this, and the nature of the RoutedEvents we just handle the MouseDown in the ListBox exactly when we want. When somewhere inside the ListBox is clicked that isn't part of an item.

private void ListBox_MouseDown(object sender, MouseButtonEventArgs e)
{
 (sender as ListBox).SelectedItem = null;
}
rmoore
Thanks, but helps a bit but I see two problems with this. First it doesn't take care of the case where you have two listboxes and you want to deselect both. Secondly it only seems to deselect one item.
Anders Rune Jensen
Setting the SelectedItem to null will always unselect all items in the listbox. If it needs to effect multiple list boxes when any one is clicked then you can simply give them an x:Name and in the MouseDown explicitly set their selected item.eg: <ListBox x:Name="uiListBox1" SelectionMode="Extended" Mouse.MouseDown="ListBox_MouseDown">..</..><ListBox x:Name="uiListBox2" SelectionMode="Extended" Mouse.MouseDown="ListBox_MouseDown">..</..>private void ListBox_MouseDown(object sender, MouseButtonEventArgs e){ uiListBox1.SelectedItem = null; uiListBox2.SelectedItem = null;}
rmoore
A: 

I've used myListBox.SelectedItems.Clear(). Most selected items collections are read-only, but not the list boxes.

Geoff Cox