У меня есть приложение, в котором есть ListBox из ListBoxes. Я хотел бы сделать поля InnerList взаимоисключающими. Моя ViewModel имеет коллекцию Foos, у которой есть описание, свойство IsSelected и коллекции Bars, у которых есть имя и свойство IsSelected.
public class MyViewModel : INotifyPropertyChanged
{
public ObservableCollection<Foo> Foos { /* code removed for brevity */ }
}
public class Foo : INotifyPropertyChanged
{
public string Description { /* code removed for brevity */ }
public ObservableCollection<Bar> Bars { /* code removed for brevity */ }
public bool IsSelected { /* code removed for brevity */ }
}
public class Bar : INotifyPropertyChanged
{
public string Name { /* code removed for brevity */ }
public bool IsSelected { /* code removed for brevity */ }
}
Ниже приведена часть моего окна MainWindow, для которого установлено значение DataContext MyViewModel. Свойство ItemsSource этого ListBox привязано с помощью ItemsSource = {Binding Path = Foos}
, а в шаблоне для этого ListBox есть внутренний ListBox, который привязан с помощью ItemsSource = "{Binding Path = Bars}"
. A, B и C - описания Фуса. Содержащиеся в них предметы являются именами бара.
|--------------------------|
| A |--------------------| |
| | Item 1 | |
| | Item 2 | |
| | Item 3 | |
| |--------------------| |
| |
| B |--------------------| |
| | Item X | |
| | Item Y | |
| | Item Z | |
| |--------------------| |
| |
| C |--------------------| |
| | Item l | |
| | Item m | |
| |--------------------| |
|--------------------------|
Мне нужно сделать так, чтобы пользователь мог выбрать только один элемент из любой панели. Итак, если пользователь выбирает элемент 1 из Foo A, а затем выбирает элемент X из Foo B, то элемент 1 должен быть отменен.
Мне также нужно привязать выбранный элемент к элементу управления TextBox в другом месте окна, но я полагаю, что это нужно делать один раз.
Сделать это в коде и событиях изменения выбора нельзя. Я бы предпочел использовать только XAML.
Заранее спасибо.
ОБНОВЛЕНИЕ
Следуя совету Moonshield, я придумал это, но это все еще не полностью работает.
public class MyViewModel
{
private Bar _selectedBar;
public ObservableCollection<Foo> Foos { /* code removed for brevity */ }
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>