【问题标题】:WPF Listbox SelectionChangedWPF 列表框选择已更改
【发布时间】:2012-05-28 15:59:59
【问题描述】:

我目前有一个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 将 IsEnabled 设置为 false,但我窥探了它并且所有控件都已启用。它只是得到一个看起来像禁用的灰色背景。将尝试进一步调查。

更新 2:当您更改项目时,似乎没有取消设置 ListBoxItem IsSelected 属性。

【问题讨论】:

  • 我不明白 c# 代码与 XAML 的关系。您可能想要更精确。
  • 给了你实体的结构,这就是为什么我在那里有 C# 代码,xaml 是我绑定它的方式。它触发良好,我尝试用不同的正常实体重现它,它的行为相同。
  • 您应该发布您的方法“测试”的代码。我很难相信这种方法不会在您描述的情况下运行。您可能没有得到您期望的结果,但这可能是因为方法的逻辑存在缺陷。您是否尝试在“测试”中设置断点?
  • 是的,我不需要为 Test 放置方法,因为它只是空方法,我只想让它触发。我确实设置了一个断点。
  • @DisplayNameismissing 我知道这是一篇很老的帖子,但不适合我回答你的问题?

标签: c# wpf listbox


【解决方案1】:

回答你的问题...

我想知道为什么 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,则您的listBox_SelectionChanged 获得触发,然后在您的listBox2 中选择Element2,以便您的listBox_SelectionChanged 再次获得触发。

如果您仔细查看listBox1,您会发现Element1 后面的Background 是灰色的,这意味着它已被选中,但没有焦点。如果您现在再次在listBox1 中选择Element1listBox_SelectionChanged 不会被触发,因为选择不会改变,只有 Focuse 会改变。

这与您的代码中的“问题”完全相同,因为您的 DataTemplate 与我们所做的相同,因为我们只是自动添加了 2 个列表框

作为简单而肮脏的解决方法,您可以使用以下代码

    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];
    }

【讨论】:

    【解决方案2】:

    我发现的简单解决方案是在事件处理程序中将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;
    }
    

    【讨论】:

      【解决方案3】:

      选择同一个项目不是一个 SelectionChanged 事件。选择没有改变。

      问题陈述不清楚。

      打破它。这对我有用。如果我第二次选择任何项目,第 3 次,第 4 次事件触发。

      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>
      

      【讨论】:

      • 当您选择另一个项目并重新选择该项目时不会。
      • 问题陈述是“选择之前选择的项目”。标记你的问题陈述不清楚而不是标记这个答案。
      • 现在表现得像个孩子,因为有人将您的答案标记为不合格,因此您会将问题标记为不合格。如果有不清楚的地方,你应该在评论中询问,不是 stackoverflow 中的每个人都有很好的英语。那你怎么说清楚呢? “选择之前选择的项目”是不是假设您之前已经选择了该项目并且您重新选择了它?
      • 我正在标记答案,因为它不清楚。一个项目来源无效 - 它没有属性到期日期。包括似乎不是问题的一部分的文本块。三“重选”仍不清楚。清除将是:第一次选择一个项目并触发事件。第一次选择另一个项目并触发事件。即使我选择另一个项目并返回,第二次选择一个项目也会触发该事件。
      • 一,某些属性的属性是否不存在也没关系。您知道如何在 WPF 中编写代码吗?其次,该问题有一个编辑选项以使其清晰。如果你改写那句话,你认为每个人都清楚,然后去编辑它,我会批准它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 2010-12-09
      相关资源
      最近更新 更多