Расширитель как ListBoxItem не вызывает выбор

У меня есть ListBox с ListBoxItem, используя DataTemplate, который использует Expander в качестве своего контейнера. Проблема в том, что Expander кажется, что есть Click event (HeaderSite часть Expander, если быть точным), и я никогда не получаю SelectedItem, если я нажимаю на Expander (но он работает, если вы нажмите на ListBoxItem).

Любая идея о том, как получить Expander, чтобы играть красиво с помощью ListBox?

Здесь упрощенный Xaml, который будет воспроизводить проблему (без необходимости кода):

Изменить обновленный код, чтобы приблизиться к моему фактическому шаблону, но скриншоты по-прежнему из предыдущей версии (проблема такая же - это просто для выяснения проблемы с первым ответом)

<Window x:Class="ListBoxSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock>
            <Run Text="Selected Item" />
            <Run Text="{Binding ElementName=ListBox, Path=SelectedItem}" />
        </TextBlock>
        <ListBox x:Name="ListBox">
            <ListBoxItem>
                <Expander Header="Expandable Stuff 1">
                    <ListBox>
                        <ListBoxItem>1.1</ListBoxItem>
                        <ListBoxItem>1.2</ListBoxItem>
                    </ListBox>
                </Expander>
            </ListBoxItem>
            <ListBoxItem>
                <Expander Header="Expandable Stuff 2">
                    <ListBox>
                        <ListBoxItem>2.1</ListBoxItem>
                        <ListBoxItem>2.2</ListBoxItem>
                    </ListBox>
                </Expander>
            </ListBoxItem>
        </ListBox>
    </StackPanel>
</Window>

Скриншоты предварительно редактируются

Нажав ListBoxItem, в результате получим SelectedItem:

Clicking on <code>ListBoxItem</code> resulting a <code>SelectedItem</code>

Нажатие на Expander приводит к обновлению нет SelectedItem (щелчок на Expander 1 был очевиден пунктиром):

Clicking on Expander resulting no <code>SelectedItem</code> update

Ответы

Ответ 1

Без кода позади вы можете сделать это

<ListBox.ItemContainerStyle>
    <Style>
        <Style.Triggers>
            <EventTrigger RoutedEvent="Control.PreviewMouseLeftButtonDown">
                <BeginStoryboard>
                    <Storyboard Storyboard.TargetProperty="(Selector.IsSelected)">
                        <BooleanAnimationUsingKeyFrames Duration="0:0:0">
                            <DiscreteBooleanKeyFrame Value="True" />
                        </BooleanAnimationUsingKeyFrames>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Style.Triggers>
    </Style>
</ListBox.ItemContainerStyle>

Ответ 2

Ну, следующий код, похоже, работает с недостатком (или, может быть, преимуществом), что в каждый момент времени будет выходить только выбранный элемент.

Примените следующие 2 атрибута к вашему 2 Expander s

IsHitTestVisible="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}"
IsExpanded="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}"

Связывая IsHitTestVisible, а также позволяет взаимодействовать с элементами, содержащимися в Expander.

Результат:

            <ListBox x:Name="ListBox" IsSynchronizedWithCurrentItem="True">
                <ListBoxItem>
                    <Expander Header="Expandable Stuff 1" IsHitTestVisible="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}" IsExpanded="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}">
                        1
                    </Expander>
                </ListBoxItem>
                <ListBoxItem>
            <Expander Header="Expandable Stuff 2" IsHitTestVisible="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}" IsExpanded="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}">
                        2
                    </Expander>
                </ListBoxItem>
            </ListBox>

Другое решение с кодом позади было бы таким:

            <ListBox x:Name="ListBox" IsSynchronizedWithCurrentItem="True">
                <ListBoxItem>
                    <Expander Header="Expandable Stuff 1" IsHitTestVisible="False" IsExpanded="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected}">
                <StackPanel IsHitTestVisible="True">
                    <Label Content="1"/>
                </StackPanel>
            </Expander>
                </ListBoxItem>
                <ListBoxItem>
            <Expander Header="Expandable Stuff 2" ButtonBase.Click="Expander_Click_1" Tag="{Binding  RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}}">
                2                     
            </Expander>
                </ListBoxItem>
            </ListBox>

И код позади:

    private void Expander_Click_1(object sender, RoutedEventArgs e)
    {
        if (sender is Expander)
        {
            Expander senderExp = (Expander)sender;
            object obj = senderExp.Tag;
            if (obj is ListBoxItem)
            {
                ((ListBoxItem)obj).IsSelected = true;
            }
        }            
    }