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;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…