#wpf
#wpf
Вопрос:
У меня есть коллекция объектов, которые я привязываю к списку, но на самом деле я хочу отображать только выбранный элемент, а не всю коллекцию. Каков наилучший способ сделать это? Использовать другой элемент управления?
Я думаю, что могу выполнить Visibility ValueConverter, который проверяет атрибут IsSelected — и, если не выбран, сворачивается… но меня все еще интересуют другие идеи.
Комментарии:
1. То есть вы хотите показать только один элемент ListBoxItem в вашем ListBox?
2. @smoore Да, но пользователь может изменить выбранный элемент с помощью кнопок [предыдущий] и [следующий].
3. Просто из любопытства, какую выгоду вы получаете от использования ListBox, если вы не перечисляете несколько элементов для выбора?
4. @smoore Наблюдаемая коллекция поступает асинхронно сериализованной из WCF. Итак, если я просто привязываюсь к элементу, кажется, что мне придется выполнять какой-то уродливый внутренний код при обновлении списка.
5. Разве это не то, что они называют ComboBox?
Ответ №1:
Поскольку вся цель a ListBox
заключается в отображении нескольких элементов и предоставлении пользователю способа их выбора, да, я бы использовал другой элемент управления.
Или вы могли бы сделать это, что входит в территорию глупости:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="false">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
Ответ №2:
Хотя я согласен с ответом Андерса, есть способ показать только выбранный элемент в ListBox
, если по какой-то причине за пределами моего воображения это действительно то, что вы хотите сделать:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Ответ №3:
Вы можете заставить WPF поддерживать «текущий элемент» для вас, не используя ListBox. На самом деле, если я правильно читаю этот пост в блоге, это происходит автоматически, когда вы устанавливаете DataContext в коллекцию.
Вы можете ссылаться на «текущий элемент коллекции», используя косую черту в вашем выражении Path.
Поскольку вы уже написали свои собственные кнопки «Next» и «Previous» (которые, предположительно, уже должны подключаться к этому механизму текущего элемента), вы можете покончить с безумием ListBox с одним элементом за раз и просто привязать текстовый блок (или что-то еще) к свойствам текущего элемента:
<TextBlock Text="{Binding /ItemText}"/>
Ответ №4:
Использовать текстовое поле. В вашей ViewModel (к которой, я полагаю, вы привязываетесь) создайте свойство, отображающее выбранный элемент (обязательно реализуйте INotifyPropertyChanged
), и привяжите текстовое поле к этому свойству.
Ответ №5:
Я пробовал что-то подобное и придумал это изящное решение:
<Expander Header="Elements" Name="FooExpander">
<Expander.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding}"/>
<ListBoxItem Content="{Binding ElementName=ElementList, Path=SelectedItem}">
<ListBoxItem.Style>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<Trigger Property="Content" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBoxItem.Style>
</ListBoxItem>
</StackPanel>
</DataTemplate>
</Expander.HeaderTemplate>
<ListBox x:Name="ElementList"
SelectionChanged="SelectionChanged"
ItemsSource="{Binding Path=Foo}"
DisplayMemberPath="Name"
/>
</Expander>
private void SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
FooExpander.IsExpanded = ((sender as ListBox).SelectedIndex == -1);
}
Может быть, вы находите это вдохновляющим.
Ответ №6:
Используйте поле со списком вместо поля списка. В выпадающем списке отображается только выбранный элемент, но вы все равно можете выбрать элемент из всего списка. Кроме того, вы можете использовать up / down для перемещения по списку.