I have an ItemsControl with DataTemplates that contain ListBoxes with ItemsSource all bound to different ObservableCollections of the same type, each ListBox's SelectedItem is bound to the same property that raises PropertyChanged so that other visual elements of my UserControl will update with the SelectedItem's details.
Everything works great except for the case where a ListBox has only one item. When I click that single item开发者_如何学编程 the first time, PropertyChanged is raised as you'd expect. If I click an item in another ListBox everything still works great. However when clicking a lone item in a ListBox that has already been selected once -- it doesn't tell SelectedItem that we've actually selected a new item since as far as the ListBox is concerned it's the same item.
I'm looking for a clean way of handling this situation. Any ideas?
For a little more involved scenarios like this i personally wouldnt use a ListBox. I just implement an IsSelectable interface (with just a IsSelected property) on the objects. Then I use a sort of SelectionContextService to register those viewmodels/objects to allow multiple independent selections on a view and handle multiselect/deselecting on new selections and stuff like this. In the datatemplates (basically views) for the viewmodels I use some attached property to define a selection behaviour (mostly just wiring MouseDown events to state changes when the DataContext is an ISelectable). This is basically doing everything manually, but i find it very easy to handle treeviews or selectable objects scattered all throughout your view this way.
When a ListBox's item is clicked, whether or not it's already selected, ListBox's GotFocus Event is fired before the SelectedItem is changed -- assuming the ListBox was out of focus. So, setting the SelectedItem to null in the GotFocus event refreshes the SelectedItem.
XAML:
<ItemsControl ItemsSource="{Binding Path=ParentCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBox GotFocus="ListBox_GotFocus"
ItemsSource="{Binding ChildCollection}"
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyView} }, Path=DataContext.SelectedChild}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Code Behind:
private void ListBox_GotFocus(object sender, RoutedEventArgs e)
{
((ListBox)sender).SelectedItem = null;
}
精彩评论