[英]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
和三個按鈕: addButton
, removeButton
和logSelectionButton
。
如果按addButton
(從一個空列表),然后removeButton
最后addButton
再次,既不SelectedValueChanged
也沒有SelectedIndexChanged
會觸發在最后addButton
按下,即使如果按logSelectionButton
前后歷時后addButton
按下,你會看到SelectedIndex
和SelectedValue
的值分別從-1變為0,從null
變為“Item 1”,並且在列表框中看起來選擇了“Item 1”。
這將導致我需要根據所選項目更新任何其他控件以保持禁用狀態,直到用戶手動選擇列表框中的項目為止,即使第一項已被選中。
我想不出任何解決方法。 也許還訂閱我的BindingList的ListChanged
事件以查看列表是否為空,但后來我不知道列表框中的項是否會在事件處理程序觸發之前或之后更新,這將導致其他問題。
好像你發現一個bug ListControl
中的內部處理PositionChanged
當數據綁定事件(如果啟用例外在VS,你會看到一個異常時,第一項被添加到空列表)。
由於ListControl
派生類(如ListBox
, ComboBox
等)在數據綁定模式下將它們的選擇與BindingManagerBase
的Position
屬性同步,因此可靠的解決方法(基本上是更通用的抽象解決方案)是處理基礎數據源綁定管理器的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.