Как заставить элементы управления дочерней таблицы WPF Listbox выбирать контейнер ListBoxItem при нажатии?

У меня есть список и в табличке с данными у меня есть Expander.

Если я щелкну заголовок Expander, он расширит зону содержимого, но не выберет родительский ListBoxItem.

Если я щелкну по Расширенной зоне содержимого Расширителя, родительский ListBoxItem станет выбранным.

Как сделать так, чтобы при нажатии на expanderHeader содержимое становилось расширенным, а родительский элемент списка становился выбранным?

4 ответа

Решение

Я столкнулся с той же проблемой и обработал ее, прослушав событие PreviewGotKeyboardFocus в ListBox. Когда изменение фокуса идет, визуальное дерево ищет ListBoxItem и выбирает его:

    private void ListBox_PreviewGotKeyboardFocus( object sender, KeyboardFocusChangedEventArgs e )
    {
        if( e.NewFocus is FrameworkElement )
        {
            ListBoxItem item = ( e.NewFocus as FrameworkElement ).FindParent<ListBoxItem>();
            if( item != null && !item.IsSelected )
            {
                item.IsSelected = true;
            }
        }
    }

    public static T FindParent<T>( this FrameworkElement element ) where T : FrameworkElement
    {
        DependencyObject current = element;

        while( current != null )
        {
            if( current is T )
            {
                return ( T ) current;
            }

            current = VisualTreeHelper.GetParent( current );
        }

        return null;
    }

Я понимаю, что на этот вопрос был дан ответ, но есть гораздо более простой способ достичь этого желаемого результата. Вы можете добавить Trigger к ListBoxItem Style который выберет ListBoxItem всякий раз, когда элемент в его ItemTemplate имеет фокус клавиатуры:

<Style.Triggers> 
  <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
    <Setter Property="IsSelected" Value="True"/> 
  </Trigger> 
</Style.Triggers>

Для получения дополнительной информации просмотрите MSDN или post1 или post2.

Ты не можешь использовать Expanded событие для этого?

что-то вроде

<Expander Expanded="Expander_Expanded"

а также

private void Expander_Expanded(object sender, RoutedEventArgs e)
{
    parentListBox.Focus();
}

Вы можете привязать свойство IsExpanded Expander напрямую к свойству IsSelected объекта ListBoxItem. Но это означает, что вы просто выбираете элемент, который расширяет тоже расширитель... И это также означает, что невыбранные элементы никогда не расширяются.

пример:

  <ListBox>
    <ListBox.ItemTemplate>
      <DataTemplate>
        <Expander IsExpanded="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=IsSelected}">
          <TextBlock Text="bla bla" />
        </Expander>
      </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.Items>
      <DataObject />
      <DataObject />
    </ListBox.Items>
  </ListBox>
Другие вопросы по тегам