根据选择一个列表框中的项目选择/取消选择多个列表框中的项目 - C# Windows 窗体

Posted

技术标签:

【中文标题】根据选择一个列表框中的项目选择/取消选择多个列表框中的项目 - C# Windows 窗体【英文标题】:Select / Deselect Items in multiple listboxes based on selection of an item in one listbox - C# Windows forms 【发布时间】:2021-11-23 04:54:35 【问题描述】:

我有一个场景,我有三个列表框。可以在列表框中选择多个项目。 根据一个列表框中的项目选择,我需要在其他列表框中选择和取消选择相应的行。

我有下面的代码,但我遗漏了一些东西。 当我选择和取消选择项目时,它会错误地选择和取消选择其他行项目。

            for (int count = 0; count < listBox_1.SelectedIndices.Count; count++)
            
                // Determine if the item is selected.
                if (listBox_1.GetSelected(count) == true)
                
                    listBox_2.SetSelected(listBox_1.SelectedIndices[count], false);
                    listBox_3.SetSelected(listBox_1.SelectedIndices[count], false);
                
                else if (listBox_1.GetSelected(count) == false)
                
                    // Select all items that are not selected.
                    listBox_2.SetSelected(listBox_1.SelectedIndices[count], true);
                    listBox_3.SetSelected(listBox_1.SelectedIndices[count], true);
                

            

这里 LB1 中的项目选择应该控制 LB2 和 LB3 中的选择。 现在,由于在 LB1 中选择了第 2 和第 3 项 - 在 LB2 和 LB3 中也应选择第 2 和第 3 项。但事实并非如此。

========================================= 更新

当用户选择 ListBox2 或 ListBox3 中的项目时,我如何复制该行为

    private void listBox_1_SelectedIndexChanged_(object sender, EventArgs e)
    
        listBox_2.ClearSelected();
        listBox_3.ClearSelected();

        int userSelectedIndex = listBox_1.Items.Count;
        if (listBox_1.SelectedIndices.Count > 0)
        
            for (int count = 0; count < listBox_1.Items.Count; count++)
            
                // Determine if the item is selected.
                if (listBox_1.GetSelected(count) == true)
                
                    if (count <= listBox_2.Items.Count)
                        listBox_2.SetSelected(count, true);
                    if (count <= listBox_3.Items.Count)
                        listBox_3.SetSelected(count, true);
                
                else if (listBox_1.GetSelected(count) == false)
                
                    // Select all items that are not selected.
                    if (count <= listBox_2.Items.Count)
                        listBox_2.SetSelected(count, false);
                    if (count <= listBox_3.Items.Count)
                        listBox_3.SetSelected(count, false);
                
            
       
    

当用户选择 ListBox 2 中的项目时,LB1 和 LB3 中的项目也应该被选中。

    private void listBox_2_SelectedIndexChanged(object sender, EventArgs e)
    
        listBox_1.ClearSelected();  // ITS giving error here.
        listBox_3.ClearSelected(); 
           
        int userSelectedIndex = listBox_2.Items.Count;
        if (listBox_2.SelectedIndices.Count > 0)
        
            for (int count = 0; count < listBox_2.Items.Count; count++)
            
                // Determine if the item is selected.
                if (listBox_2.GetSelected(count) == true)
                
                    if (count <= listBox_1.Items.Count)
                        listBox_1.SetSelected(count, true);
                    if (count <= listBox_3.Items.Count)
                        listBox_3.SetSelected(count, true);
                
                else if (listBox_2.GetSelected(count) == false)
                
                    // Select all items that are not selected.
                    if (count <= listBox_1.Items.Count)
                        listBox_1.SetSelected(count, false);
                    if (count <= listBox_3.Items.Count)
                        listBox_3.SetSelected(count, false);
                
            
       
    

【问题讨论】:

“但我错过了一些东西。” ...不是问题。什么没有按预期工作? @JohnG - 更新 - 它错误地选择和取消选择其他行项目。 好的,我认为这更清楚了。当用户选择/取消选择列表框 1 中的一行时,什么会被认为是“正确的”?什么会被认为是“不正确的”?当另一个列表框中的另一行被选择/取消选择时,我们不知道是什么决定了应该选择/取消选择哪个列表框行。你能举个例子吗? @JohnG - 更新了一个例子。希望这会有所帮助。 或者简单地使用foreach 循环遍历SelectedIndicies 集合。类似...foreach (int selectedIndex in listBox_1.SelectedIndices) ......发布的代码在哪里被调用? 【参考方案1】:

不清楚这段代码在哪里被调用。我会简单地清除其他 list2 和 list3 框,然后设置与列表框 1 中相同的选定索引...类似于...

listBox_2.ClearSelected();
listBox_3.ClearSelected();
foreach (int selectedItem in listBox_1.SelectedIndices) 
  listBox_2.SetSelected(selectedItem, true);
  listBox_3.SetSelected(selectedItem, true);

根据 OP 评论进行编辑……

我仍然没有遵循要求,但是,如果您希望所有 ListBoxes 在每个 ListBox 中都具有“相同的选定索引”,那么下面的代码可能会有所帮助。

您当前的解决方案可能遇到的一个问题是可能的循环引用。例如,listBox_1_SelectedIndexChanged代码中,有一行代码……

listBox_2.SetSelected(count, true);

... 这会在列表框 2 中设置选定的索引,这将触发 listBox_2_SelectedIndexChanged 事件。然后......在那个事件代码中你有代码......

listBox_1.SetSelected(count, true);

...这将“再次”触发列表框 1 事件。

很明显,这可能会创建一个无限循环引用,其中每个事件只是调用另一个事件并且永远不会结束。

鉴于事件中的代码可能需要在另一个ListBoxes 中“设置”一个索引,那么可能需要在代码之前从其SelectedIndexChanged 事件中关闭/取消订阅列表框设置索引,然后在设置索引后开启/重新订阅事件。

因此在下面的解决方案中,由于所有三个ListBoxes 都使用相同的事件,因此代码在代码开始之前关闭/取消订阅每个ListBox 事件,然后打开/重新启动完成后订阅事件。

此外,正如@zaggler 正确指出的那样,检查ListBox 是否确实具有给定值的索引,有必要在设置索引之前检查索引是否在有效范围内,以避免索引超出边界异常。

private void listBox_SelectedIndexChanged(object sender, EventArgs e) 
  listBox_1.SelectedIndexChanged -= new EventHandler(listBox_SelectedIndexChanged);
  listBox_2.SelectedIndexChanged -= new EventHandler(listBox_SelectedIndexChanged);
  listBox_3.SelectedIndexChanged -= new EventHandler(listBox_SelectedIndexChanged);
  ListBox lb_1 = (ListBox)sender;
  ListBox lb_2;
  ListBox lb_3;
  switch (lb_1.Name) 
    case "listBox_1":
      lb_2 = listBox_2;
      lb_3 = listBox_3;
      break;
    case "listBox_2":
      lb_2 = listBox_1;
      lb_3 = listBox_3;
      break;
    default:
      lb_2 = listBox_1;
      lb_3 = listBox_2;
      break;
  
  lb_2.ClearSelected();
  lb_3.ClearSelected();

  foreach (int selectedItem in lb_1.SelectedIndices) 
    if (selectedItem < lb_2.Items.Count) 
      lb_2.SetSelected(selectedItem, true);
    
    if (selectedItem < lb_3.Items.Count) 
      lb_3.SetSelected(selectedItem, true);
    
  
  listBox_1.SelectedIndexChanged += new EventHandler(listBox_SelectedIndexChanged);
  listBox_2.SelectedIndexChanged += new EventHandler(listBox_SelectedIndexChanged);
  listBox_3.SelectedIndexChanged += new EventHandler(listBox_SelectedIndexChanged);

【讨论】:

John - 在 listBox_1_SelectedIndexChanged(object sender, EventArgs e) 处调用代码 那么我发布的代码应该可以工作了。 确实如此。 ClearSelected() 是我所缺少的。谢谢约翰 @JNL 你没有错过ClearSelected,你的条件倒退了。 @zaggler - 你能帮忙编辑问题吗?当用户选择 ListBox 2/ ListBox 3 中的项目时,如何复制行为【参考方案2】:

这里 LB1 中的项目选择应该控制 LB2 和 LB3 中的选择。现在,由于在 LB1 中选择了第 2 和第 3 项 - 在 LB2 和 LB3 中也应选择第 2 和第 3 项。但事实并非如此。

我建议遍历listBox_1...的所有项目...

for (int idx = 0; idx <= listBox_1.Items.Count - 1; idx++)
            
                if (listBox_1.GetSelected(idx))
                
                    if (idx <= listBox_2.Items.Count)
                        listBox_2.SetSelected(idx, true);
                    if (idx <= listBox_3.Items.Count)
                        listBox_3.SetSelected(idx, true);
                
                else
                
                    if (idx <= listBox_2.Items.Count)
                        listBox_2.SetSelected(idx, false);
                    if (idx <= listBox_3.Items.Count)
                        listBox_3.SetSelected(idx, false);
                
            

请注意,我也进行了检查以确保索引存在,否则如果索引不存在,它可能会抛出错误。

【讨论】:

感谢您的帮助@zaggler。 @JNL 欢迎,如果使用 JohnG 答案,我会检查索引是否存在,否则会抛出异常。

以上是关于根据选择一个列表框中的项目选择/取消选择多个列表框中的项目 - C# Windows 窗体的主要内容,如果未能解决你的问题,请参考以下文章

WPF:停止或反转列表框中的选择更改

删除列表框中的多个选定项目 - 仅识别第一个选择的代码

从列表框中选择多个项目以附加到电子邮件中

根据 Access 列表框中的选择打开子表单

Csharp:根据组合框中的值加载选中的项目列表

如何根据列表框中的选定行填充多个文本框