2017-02-21 10 views
4

現在選択されている値に従って他のコントロールを更新/無効にするには、ListBoxで選択したアイテムを追跡する必要があります。ListBox SelectedValueChanged/SelectedIndexChangedデータソースが変更されたときに起動しない

この問題を再現するためのコードです:addButtonremoveButtonlogSelectionButton

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と3つのボタンがあります。

あなたは(空のリストから始まる)addButtonを押した場合は、removeButton、最後にaddButton再び、SelectedValueChangedSelectedIndexChangedどちらもあなたが最後addButtonプレスの前と後のlogSelectionButtonを押してもかかわらず、最後addButton押すだけで起動します、あなたはSelectedIndexSelectedValueの値がそれぞれ-1から0に、nullから「項目1」に変更され、リストボックスで「項目1」が選択されていることがわかります。

これは、最初のアイテムが既に選択されていても、ユーザーが手動でリストボックスのアイテムを選択するまで、選択したアイテムに応じて更新する必要があるその他のコントロールを無効にします。

いずれの回避策も考えられません。また、BindingListのListChangedイベントを購読して、リストが空かどうかを確認しますが、イベントハンドラが起動する前または後にリストボックスの項目が更新されるかどうかはわかりません。

答えて

3

データがバインドされたときにイベントの内部処理でバグが見つかったようです(VSで例外をオンにすると、最初の項目が空のリストに追加されたときに例外が表示されます)。

ListControlので、派生クラスListBoxように、モード結合データにComboBoxなどBindingManagerBasePosition性、信頼性の問題を回避する(基本的には、より一般的な抽象溶液)との選択は、基礎となるデータのCurrentChangedイベントを処理することで同期ソースバインディングマネージャー:

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

これは動作するようには思えません。明らかに、選択が実際に変更される前に 'CurrentChanged'が発生し、現在選択されている項目を追跡する必要があります。私は別の解決策を見つけました(自分の回答を参照)。 – Juan

+0

お望みです。なぜなら、バインディングマネージャの 'Current'プロパティを通して同じものが利用可能になったときに、コントロールの選択が変更されて、それが正しいのであれば、なぜあなたが気にしているのかわかりません。すべての自動マスターディテールバインディングとナビゲータは、特定のコントロールイベント/プロパティに反応するのではなく、そのアプローチを使用します。 –

+0

「Current」から選択した値を取得できるかどうかわかりませんでした。ニースのアプローチ。 – Juan

0

正常に動作するように見える回避策が見つかりました。リストボックスが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(); 
    } 
} 
関連する問題