WPF列表框SelectionChanged

4

我目前有一个实体(Entity),它有一个集合属性。我想知道为什么当我尝试选择先前选择的项目时,SelectionChanged仅会触发一次,并且不会再次触发SelectionChanged

MainWindowViewModel

  public MainWindowViewModel()
    {
        var a = new List<Test>();

        a.Add(new Test() { Name = "Leo", Test1 = new List<Test1> { new Test1() { Content = "aaa"} } });
        a.Add(new Test() { Name = "2", Test1 = new List<Test1> { new Test1() { Content = "bbb"} } });
        a.Add(new Test() { Name = "Le33o", Test1 = new List<Test1> { new Test1() { Content = "ccc"} } });
        A = a;
    }

    private List<Test> _a;
    public List<Test> A
    {
        get { return _a; }
        set { _a = value; OnPropertyChanged("A");}
    }

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

我的主窗口

public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
        private void Test(object sender, SelectionChangedEventArgs e)
        {
        }

我的列表框结构

public class Test
{
    public List<Test1> Test1 { get; set; }
    public string Name
    {
        get;set;
    }
}

public class Test1
{
    public string Content { get; set; }
}

我选择第一个对象,事件触发,我选择第二个对象,事件再次触发,我重新选择第一个对象,事件不再触发,当我选择第三个对象时,事件又被触发了。似乎它只会触发和调用一次事件。

我的XAML代码:

<ItemsControl x:Name="Lists" ItemsSource="{Binding A}" Grid.Row="1">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <TextBlock Text="{Binding Name}" FontWeight="Bold" 
                                                        Style="{StaticResource DefaultTextBlockStyle}" />

                    <ListBox  SelectionChanged="Test"  ItemsSource="{Binding Test1}"
                                 Margin="5,0,0,0" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Content}" />
                                </StackPanel>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

测试方法只是一个空的方法,我只是想在每次更改时打断点。
  private void Test(object sender, SelectionChangedEventArgs e)
    {
    }

更新1: 我尝试在一个简单的WPF应用程序中复现这个问题,似乎ListBoxItem被设置为false但我使用Snoop检查后发现所有控件都是可用的。它只是变成了一种看起来像被禁用的灰色背景。我将进一步调查。

更新2: 当你改变一个项目时,ListBoxItem的IsSelected属性没有被取消选择。


我不明白C#代码和XAML的关系,你可能需要更加精确。 - JohnB
我给你提供了实体的结构,这就是为什么我在那里放置了C#代码,xaml是我如何绑定它的。它可以正常触发,我尝试使用不同的普通实体进行复制,结果行为相同。 - 123 456 789 0
你应该发布你的“Test”方法的代码。我很难相信在你描述的情况下这个方法不会运行。你可能没有得到你期望的结果,但这可能是因为方法逻辑上的缺陷。你尝试在“Test”中设置断点了吗? - Lee O.
是的,我不需要为Test方法编写代码,因为它只是一个空方法,我只想让它触发。我已经设置了断点。 - 123 456 789 0
@DisplayName缺失 我知道这是一个非常老的帖子,但它是否符合您的问题? - WiiMaxx
3个回答

6
为了回答你的问题...

我想知道为什么SelectionChanged只会触发一次,当我尝试选择之前已经选中的项时,它不会再次触发SelectionChanged。

在实践中学习的过程中,打开一个新的WPF项目,添加2个列表框,为两者创建一个SelectionChanged事件并向每个列表框添加一些项目。
现在看起来是这样的。
    <ListBox Height="100" Name="listBox1" Width="120" SelectionChanged="listBox_SelectionChanged"/>
    <ListBox Height="100" Name="listBox2" Width="120" SelectionChanged="listBox_SelectionChanged"/>

.

        var list = new List<string>();
        list.Add("Element1");
        list.Add("Element2");
        list.Add("Element3");
        list.Add("Element4");

        listBox1.ItemsSource = list;
        listBox2.ItemsSource = list;

如果您现在在listBox1中选择Element1,则在选择listBox2中的Element2后,listBox_SelectionChanged将再次被触发。
如果您仔细查看listBox1,您会发现Element1后面的Background是灰色的,这意味着它已被选中,但没有焦点。如果您现在再次在listBox1中选择Element1,则listBox_SelectionChanged不会被触发,因为选择没有改变,只有焦点改变了。
这与您的代码中的问题完全相同,因为您的DataTemplate执行了我们添加2个Listbox时自动执行的相同操作。
作为简单而粗略的解决方法,您可以使用以下代码。
    private object seletedItem;
    private ListBox ItemsHost;

    private void Test(object sender, SelectionChangedEventArgs e)
    {
        var buff = sender as ListBox;

        if (seletedItem != null)
            if (ItemsHost != buff)
                ItemsHost.SelectedItem = null;

        ItemsHost = buff;

        if (e.AddedItems.Count > 0)
            seletedItem = e.AddedItems[0];
    }

0
我找到的简单解决方案是在事件处理程序中将selectedItem设置为null
private void tempList_SelectionChanged(object sender, SelectionChangedEventArgs e)

{    
    Card selectedOffer = (TempList.SelectedItem as Card);
    if (selectedOffer != null)
    {
        MessageBox.Show(selectedOffer._id);
    }
    ListBoxNeeded.SelectedItem = null;
}

-4

选择相同的项目不是SelectionChanged事件。选择没有改变。

问题陈述不清楚。

分解它。这对我有用。如果我第二次、第三次、第四次选择任何项目,事件就会触发。

OP声称如果是列表中的列表,则无法正常工作。但对我来说仍然有效。

    public MainWindow()
        {
            this.DataContext = this;
            InitializeComponent();
        }

        public List<ListList> ListList1 
        {
            get { return new List<ListList>{new ListList("name1", new List<string> { "one", "two", "three" })}; } 
        }

        private void Test(object sender, SelectionChangedEventArgs e)
        {
            ListBox lb = (ListBox)sender;
            System.Diagnostics.Debug.WriteLine(lb.SelectedItem.ToString());
        }

        public class ListList
        {
            public string Name { get;  set; }
            public List<string> Values { get;  set; }
            public ListList(string name, List<string> values) { Name = name; Values = values; }
        }

<ListBox ItemsSource="{Binding Path=ListList1}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <ListBox  SelectionChanged="Test" ItemsSource="{Binding Path=Values}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding}" />
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

2
问题陈述是“选择之前选择的项目”。如果问题陈述不清晰,请扣分问题陈述,而不是扣分答案。 - paparazzo
2
现在你像个孩子一样行事,因为有人将你的答案标记为不好,所以你会将问题标记为不好。如果有什么不清楚的地方,你应该在评论中询问,因为并非所有在stackoverflow上的人都擅长英语。那么你要如何让它变得清晰呢?“选择先前选择的项目”难道不应该意味着你之前已经选择了该项目,现在重新选择它吗? - 123 456 789 0
我会将答案打分降低,因为它不够清晰。其中一个项目源无效 - 它没有Due Date属性。包括一些似乎不是问题的TextBlocks。而且,“重新选择”仍然不够清晰。更清晰的表述应该是:第一次选择一个项目时事件会触发。第一次选择另一个项目时事件也会触发。即使我选择另一个项目并返回,再次选择同一个项目也会触发事件。 - paparazzo
你是提问者,询问我是否能编写代码。请先自己尝试解决问题并整理好问题描述。只有在提供可重现问题的代码和数据时,才能得到更好的答案。 - paparazzo
顺便说一下,检查一下我的更新的结构。你的解决方案应该是按预期工作的,但尝试一个具有List属性的实体。 - 123 456 789 0
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接