ListBoxを配置して、適当に数値だけをメンバに持つオブジェクトをリストにして
ItemsSourceに格納します。
検証環境のビルドターゲットは.NET 4.0。
//リスト項目クラス public sealed class NumItem { readonly int num; public NumItem(int num) { this.num = num; } public override string ToString() { return num.ToString(); } public override bool Equals(object obj) { var other = obj as NumItem; if (other == null) return false; //数値が同じなら等価とみなす return this.num == other.num; } public override int GetHashCode() { return this.num.GetHashCode(); } }
//1,2,3の3行をリスト化 listbox.ItemsSource = new[] { 1, 2, 3 }.Select(n => new NumItem(n)).ToArray();
この状態でSelectedItemプロパティに、存在しない項目(4)を設定する。
すると、選択できるわけがないので、
そのあとにSelectedItemプロパティを参照するとNullが返るし、
SelectedIndexは-1を返す。
listbox.SelectedItem = new NumItem(4); Console.WriteLine(listbox.SelectedItem == null); // true Console.WriteLine(listbox.SelectedIndex); // -1
SelectedItemを設定する代わりに、SelectedIndex = 3 などとやっても同じ結果。
ここまでは想定どおりである。
ところが、そのあとに項目4を含むリストをItemSourceに再設定してやると、
なんとさっきの情報を覚えていて、
おせっかいにも勝手に選択してくれやがるじゃないですか。
listbox.SelectedItem = new NumItem(4); listbox.ItemsSource = new[] { 1, 2, 3, 4 }.Select(n => new NumItem(n)).ToArray(); Console.WriteLine(listbox.SelectedItem); // 4 Console.WriteLine(listbox.SelectedIndex); // 3
SelectedIndex = 3とやった場合もやはり同じ結果になる。
おそらく直前に設定された値を内部的に覚えてるんだろうな。
もちろんリストに存在しない項目を選択するなんていう
気持ち悪いことをやらなきゃいい話なんだけど、
というか自分ではこんなコード書かないだろうけども、
他の人の作ったアプリが変な挙動していて
調査してたらここに原因があってだいぶはまりましたとさ。