簡體   English   中英

列表框SelectedValueChanged / SelectedIndexChanged在數據源更改時不觸發

[英]ListBox SelectedValueChanged/SelectedIndexChanged not firing when data source changes

我需要跟蹤ListBox上的所選項目,以根據當前選擇的值更新/禁用其他控件。

這是重現問題的代碼:

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

我的表單有一個列表框listBox1和三個按鈕: addButtonremoveButtonlogSelectionButton

如果按addButton (從一個空列表),然后removeButton最后addButton再次,既不SelectedValueChanged也沒有SelectedIndexChanged會觸發在最后addButton按下,即使如果按logSelectionButton前后歷時后addButton按下,你會看到SelectedIndexSelectedValue的值分別從-1變為0,從null變為“Item 1”,並且在列表框中看起來選擇了“Item 1”。

這將導致我需要根據所選項目更新任何其他控件以保持禁用狀態,直到用戶手動選擇列表框中的項目為止,即使第一項已被選中。

我想不出任何解決方法。 也許還訂閱我的BindingList的ListChanged事件以查看列表是否為空,但后來我不知道列表框中的項是否會在事件處理程序觸發之前或之后更新,這將導致其他問題。

好像你發現一個bug ListControl中的內部處理PositionChanged當數據綁定事件(如果啟用例外在VS,你會看到一個異常時,第一項被添加到空列表)。

由於ListControl派生類(如ListBoxComboBox等)在數據綁定模式下將它們的選擇與BindingManagerBasePosition屬性同步,因此可靠的解決方法(基本上是更通用的抽象解決方案)是處理基礎數據源綁定管理器的CurrentChanged事件:

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

我找到了一個似乎工作正常的解決方法。 由於ListBox通過設置SelectedIndex屬性來更新所選索引,並且屬性是虛擬的,因此我可以覆蓋它以跟蹤它:

public class ListBoxThatWorks : ListBox
{
    private int LatestIndex = -1;
    private object LatestValue = null;

    public EqualityComparer<object> ValueComparer { get; set; }

    public override int SelectedIndex
    {
        get { return base.SelectedIndex; }
        set { SetSelectedIndex(value); }
    }

    private void NotifyIndexChanged()
    {
        if (base.SelectedIndex != LatestIndex)
        {
            LatestIndex = base.SelectedIndex;
            base.OnSelectedIndexChanged(EventArgs.Empty);
        }
    }

    private void NotifyValueChanged()
    {
        if (!(ValueComparer ?? EqualityComparer<object>.Default).Equals(LatestValue, base.SelectedValue))
        {
            LatestValue = base.SelectedValue;
            base.OnSelectedValueChanged(EventArgs.Empty);
        }
    }

    private void SetSelectedIndex(int value)
    {
        base.SelectedIndex = value;
        NotifyIndexChanged();
        NotifyValueChanged();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM