WPF Listbox + Expander事件

IUn*_*own 5 wpf events listbox expander

我在ListBox的ItemTemplate中有一个Expander.渲染很好.我遇到的问题是我希望扩展和/或选择扩展器时触发ListBox_SelectionChanged事件.MouseDown事件似乎没有冒泡到ListBox.

我需要的是ListBox的SelectedIndex.因为ListBox_SelectionChanged没有被触发,索引是-1,我无法确定选择了哪个项目.

如果用户在展开后单击扩展器的内容,则会触发ListBox_SelectionChanged事件.如果他们只点击扩展器,则不会触发该事件.这让用户感到困惑,因为在视觉上,他们认为他们在实际点击Expander Header时已经点击了该项目.我需要在用户扩展扩展器时选择ListBox项目,因为就用户而言,该项目现在被选中,而实际上并非如此.

有关如何使其工作的任何建议或使用扩展器确定列表框的SelectedIndex的替代方法?

简化代码供参考:

<Window x:Class="WpfApplication3.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
    Loaded="Window_Loaded">
    <Grid Name="Root">
        <ScrollViewer>
            <ListBox SelectionChanged="ListBox_SelectionChanged" ItemsSource="{Binding}">
                <ItemsControl.ItemTemplate >
                    <DataTemplate>
                        <Border>
                            <Expander>
                                <Expander.Header>
                                    <TextBlock Text="{Binding Path=Name}"/>
                                </Expander.Header>
                                <Expander.Content>
                                    <StackPanel>
                                        <TextBlock Text="{Binding Path=Age}"/>
                                        <TextBlock Text="Line 2"/>
                                        <TextBlock Text="Line 3"/>
                                    </StackPanel>
                                </Expander.Content>
                            </Expander>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ListBox>
        </ScrollViewer>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

简单的绑定类:

public class Person
{
    public string Name {
        get;
        set;
    }

    public int Age {
        get;
        set;
    }
}
Run Code Online (Sandbox Code Playgroud)

创建和填充绑定数据:

private void Window_Loaded(object sender, RoutedEventArgs e) {

    data = new ObservableCollection<Person>();

    data.Add(new Person {
        Name = "One",
        Age=10
    });

    data.Add(new Person {
        Name = "Two",
        Age = 20
    });

    data.Add(new Person {
        Name = "Three",
        Age = 30
    });

    Root.DataContext = data;
}
Run Code Online (Sandbox Code Playgroud)

这是我需要的事件(实际上只是我需要的SelectedIndex)

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    ListBox box = (ListBox)sender;

    // This value is not set because events from Expander are not bubbled up to fire SelectionChanged Event
    int index = box.SelectedIndex;
}
Run Code Online (Sandbox Code Playgroud)

Job*_*Joy 1

另一种不依赖于 IsSelected 的方法是,您可以将扩展器的 Expanded/Collapsed 事件挂钩到后面的代码,并使用以下代码查找您单击的 ListBox 索引。

DependencyObject dep = (DependencyObject)e.OriginalSource;

while ((dep != null) && !(dep is ListViewItem))
{
   dep = VisualTreeHelper.GetParent(dep);
}

if (dep == null)
     return;

int index = yourListBox.ItemContainerGenerator.IndexFromContainer(dep);
Run Code Online (Sandbox Code Playgroud)