WPF 列表框 + 扩展器事件

标签 wpf events listbox expander

我在 ListBox 的 ItemTemplate 中有一个扩展器。渲染得很好。我遇到的问题是,我希望在展开和/或选择扩展器时触发 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>

绑定(bind)的简单类:
public class Person
{
    public string Name {
        get;
        set;
    }

    public int Age {
        get;
        set;
    }
}

创建和填充数据以进行绑定(bind):
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;
}

这是我需要的事件(真的只是我需要的 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;
}

最佳答案

您想要的是让 Expander 控件控制 ListBox 选择。您可以通过将 Expander 的 IsExpanded 属性上的 TwoWay Binding 设置为您单击的直接 ListBoxItem 来轻松存档。

 <Expander IsExpanded="{Binding IsSelected,Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">

更新:如果您需要避免在选择另一个项目时自动折叠,请将列表框选择模式设置为多个。
<ListBox SelectionMode="Multiple"

关于WPF 列表框 + 扩展器事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1183326/

相关文章:

c# - 为什么使用空 lambda 函数注册到事件会导致内存中的强引用?

c# - 基于其他列表框 C# 数据库的列表框结果

c# - 列表框 IsSelected with SelectionMode=Extended

c# - ObservableCollection<T> 不更新 ListBox

wpf - 如何知道我的 WPF 应用程序可以播放哪些视频格式?

c# - 获取ListView中选中的Item的索引

wpf - WPF Sub-MenuItem在左侧而不是右侧打开

wpf - 有没有比网格更好的方法来排列 WPF 中的控件?

javascript - 将 off() 用于未定义事件时,jQuery 会抛出错误吗?

mysql - nodejs中事件驱动事务中的数据库插入/更新