Привязать к списку, но показывать только выбранный элемент?

#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 для перемещения по списку.