当数据源更改时,ListBox SelectedValueChanged/SelectedIndexChanged 不会触发 [英] ListBox SelectedValueChanged/SelectedIndexChanged not firing when data source changes

查看:30
本文介绍了当数据源更改时,ListBox SelectedValueChanged/SelectedIndexChanged 不会触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要跟踪 ListBox 上的选定项,以根据当前选定的值更新/禁用其他控件.

这是重现问题的代码:

公共部分类 Form1 : Form{私有只读 BindingListList = new BindingList();公共 Form1(){初始化组件();listBox1.DataSource = 列表;listBox1.SelectedValueChanged += (s, e) =>System.Diagnostics.Debug.WriteLine("VALUE");listBox1.SelectedIndexChanged += (s, e) =>System.Diagnostics.Debug.WriteLine("INDEX");addButton.Click += (s, e) =>List.Add("项目" + (List.Count + 1));removeButton.Click += (s, e) =>List.RemoveAt(List.Count - 1);logSelectionButton.Click += (s, e) =>{System.Diagnostics.Debug.WriteLine("选定索引:" + listBox1.SelectedIndex);System.Diagnostics.Debug.WriteLine("选定值:" + listBox1.SelectedValue);};}}

我的表单有一个列表框 listBox1 和三个按钮:addButtonremoveButtonlogSelectionButton.>

如果你按下addButton(从一个空列表开始),然后removeButton,最后再次addButtonSelectedValueChangedcode> 或 SelectedIndexChanged 将在最后一次 addButton 按下时触发,即使您在最后一次 addButtonlogSelectionButtoncode> 按下,你会看到 SelectedIndexSelectedValue 的值都从 -1 变成了 0,从 null 变成了Item1",并且项目 1"看起来在列表框中被选中.

这将导致我需要根据所选项目更新的任何其他控件保持禁用状态,直到用户手动选择列表框中的项目,即使第一个项目已被选中.

我想不出任何解决方法.也许还订阅了我的 BindingList 的 ListChanged 事件以查看列表是否为空,但是我不知道列表框中的项目是否会在我的事件处理程序触发之前或之后更新,这会导致其他问题.

解决方案

您似乎在 ListControl 内部处理 PositionChanged 数据绑定时的事件 (如果你在 VS 中打开 Exceptions,当第一项被添加到空列表时你会看到一个异常).

由于ListControl 派生类如ListBoxComboBox 等在数据绑定模式下将它们的选择与Position BindingManagerBase 的属性,可靠的解决方法(基本上是更通用的抽象解决方案)是处理 CurrentChanged 底层数据源绑定管理器的事件:

listBox1.BindingContext[List].CurrentChanged += (s, e) =>System.Diagnostics.Debug.WriteLine("当前");

I need to keep track of the selected item on a ListBox to update/disable other controls according to the currently selected value.

This is the code to reproduce the issue:

public partial class Form1 : Form
{
    private readonly BindingList<string> List = new BindingList<string>();

    public Form1()
    {
        InitializeComponent();
        listBox1.DataSource = List;

        listBox1.SelectedValueChanged += (s, e) => System.Diagnostics.Debug.WriteLine("VALUE");
        listBox1.SelectedIndexChanged += (s, e) => System.Diagnostics.Debug.WriteLine("INDEX");

        addButton.Click += (s, e) => List.Add("Item " + (List.Count + 1));
        removeButton.Click += (s, e) => List.RemoveAt(List.Count - 1);

        logSelectionButton.Click += (s, e) =>
        {
            System.Diagnostics.Debug.WriteLine("Selected Index: " + listBox1.SelectedIndex);
            System.Diagnostics.Debug.WriteLine("Selected Value: " + listBox1.SelectedValue);
        };
    }
}

My form has a list box listBox1 and three buttons: addButton, removeButton and logSelectionButton.

If you press addButton (starting with an empty list), then removeButton and finally addButton again, neither SelectedValueChanged nor SelectedIndexChanged will fire at the last addButton press, even though if you press logSelectionButton before and after the last addButton press, you'll see that the values of both SelectedIndex and SelectedValue have changed from -1 to 0 and from null to "Item 1" respectively, and that "Item 1" looks selected on the list box.

This would cause any other controls I need to update according to the selected item to stay disabled until the user manually selects an item on the list box, even though the first item is already selected.

I can't think of any workaround. Perhaps also subscribing to my BindingList's ListChanged event to see whether the list is empty or not, but then I don't know if the items in the list box will be updated before or after my event handler fires, which will cause other problems.

解决方案

Seems like you found a bug in ListControl internal handling of the PositionChanged event when data bound (if you turn Exceptions on in VS, you'll see an exception when the first item is added to the empty list).

Since ListControl derived classes like ListBox, ComboBox etc. in data bound mode synchronize their selection with the Position property of the BindingManagerBase, the reliable workaround (and basically a more general abstract solution) is to handle CurrentChanged event of the underlying data source binding manager:

listBox1.BindingContext[List].CurrentChanged += (s, e) =>
    System.Diagnostics.Debug.WriteLine("CURRENT");

这篇关于当数据源更改时,ListBox SelectedValueChanged/SelectedIndexChanged 不会触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆