I have an application that has a ListBox ListBoxes. I would like to make the InnerList fields mutually exclusive. My ViewModel has a collection of Foos that have a description, IsSelected property, and collections. Bars that have the name and property IsSelected.
public class MyViewModel : INotifyPropertyChanged { public ObservableCollection<Foo> Foos { } } public class Foo : INotifyPropertyChanged { public string Description { } public ObservableCollection<Bar> Bars { } public bool IsSelected { } } public class Bar : INotifyPropertyChanged { public string Name { } public bool IsSelected { } }
The following is part of my MainWindow whose DataContext is set to MyViewModel. This ListBox ItemsSource property is bound using ItemsSource={Binding Path=Foos} and in the template for this ListBox is an internal ListBox associated with using ItemsSource="{Binding Path=Bars}" . A, B and C are descriptions of Foos. The elements contained in them are the names of the bars.
|--------------------------| | A |--------------------| | | | Item 1 | | | | Item 2 | | | | Item 3 | | | |--------------------| | | | | B |--------------------| | | | Item X | | | | Item Y | | | | Item Z | | | |--------------------| | | | | C |--------------------| | | | Item l | | | | Item m | | | |--------------------| | |--------------------------|
I need to make the user select only one element from any of the bars. So, if the user selects item 1 from Foo A, then selects the element X from Foo B, then element 1 should be canceled.
I also need to bind the selected item to the TextBox control elsewhere in the window, but, in my opinion, 1 thing.
Doing this in code and selecting modified events is not an option. I would prefer to keep this only with XAML.
Thanks in advance.
UPDATE
Following Moonshield's advice, I came up with this, but it still doesn't work.
public class MyViewModel { private Bar _selectedBar; public ObservableCollection<Foo> Foos { } public Bar SelectedBar { get { return _selectedBar; } set { _selectedBar = null; NotifyPropertyChanged("SelectedBar"); _selectedBar = value; NotifyPropertyChanged("SelectedBar"); } } }
<ListBox x:Name="lbFoos" ItemsSource="{Binding Path=Foos}" SelectedItem="{Binding Path=SelectedBar}"> <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <StackPanel> <TextBlock Text="Foo: " /> <TextBlock Text="{Binding Path=Description}" /> <ListBox ItemsSource="{Binding Path=Bars}" SelectedItem="{Binding Path=SelectedItem RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBox}}}"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <TextBlock Text="{Binding Path=Name}" /> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=OneWayToSource}" /> </Style> </ListBox.ItemContainerStyle> </ListBox> </StackPanel> </ControlTemplate> </Setter.Value> </Setter> </Style> </ListBox.ItemContainerStyle> </ListBox>