- - PR -
ListBoxでのSelectedIndexChangedイベントの動作について
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-11-01 13:28
「書かれていない」「書かなかった」という事実のみだと思います。
ListBoxのItemはObject(型)です。つまりなんでも追加できます。 見た目に表示されているのは、DisplayMemberを設定しない場合、Object.ToString()の結果が採用されます。 Object.ToString()は派生先でオーバーライドしなければ型の表示用文字列が返されます。 ここら辺はリストボックスやコンボボックスの説明にちゃんと書かれていますよ。
2を踏まえたうえで仕様上欲する値そのものであれば問題ないでしょう。 ただし、リストボックスの場合は「表示するための文字列」であることを意識してください。 処理データと表示データを区別しましょうという意味です。 たとえば、 Private Class ListData Public P1 As String Protected Overrides Function ToString() As String Return P1 End Function End Class というクラスインスタンスをItemに追加したとします。 リストボックスにはToStringの結果が表示されます。 選択されていればTextプロパティにはそれが格納されます。 ここで、処理の仕様として「選択されたアイテムからP1を求めて〜」であるとします。 上記コードではToStringはP1そのものを返します。 つまりTextプロパティを参照しても動作することになります。 しかし、先にいった考え方でいくと 選択されたItemからListDataのインスタンスを求めてP1フィールドを参照する というのが正解となります。 | ||||||||||||||||
|
投稿日時: 2007-11-01 16:08
まどかさん、色々ありがとうございました。
この辺のことは私の力不足で、まだ理解できていませんがこれから勉強いたします。 おかげさまでフォームを閉じるときにエラー解除策が理解でき大変助かりました。 これからもよろしくお願いいたします。 | ||||||||||||||||
|
投稿日時: 2007-11-01 22:15
それはちょっと違うとおもいます。 SelectedIndexChanged は、SelectedIndex が変化した後に発生します。 フォームを閉じるときに何らかの要因で SelectedIndex が「変化する」と考えるのが妥当かと思います。 で、この「テスト」といっているものは SelectedIndexChanged イベント ハンドラしか見ていないと思います。 ブレーク ポイントを張って止めてみたとか、メッセージ ボックスを表示させたとか。 本当にフォームを閉じることが、SelectedIndex を変更することなく SelectedIndexChanged を発生させている(だんじりさんの疑問は、この形かと思います)かどうかを確認するには、SelectedIndexChanged イベントハンドラ内でブレークし、呼び出し履歴を確認する必要があると思います。 もちろん、閉じる前にどんな値だったかもメモしておく必要があるでしょう。
だから、ちゃんと読もうよ。
| ||||||||||||||||
|
投稿日時: 2007-11-02 09:10
「発生することがあるよ」という記述がどこにも見受けられなかったという事実に対して 「なぜ書かれていないのか」という疑問だと理解してそのように答えました。 #対象の説明サイトが一般サイトでしたし、仕様の話ではないと理解
今気が付いた(汗 | ||||||||||||||||
|
投稿日時: 2007-11-02 13:24
Jittさん、まどかさん、ありがとうございます。
テストの内容は次のように行いました。 ListBox1_SelectedIndexChangedイベント ハンドラに次のコードのみを記述し、 リストボックスの項目選択時とフォームクローズ時の内容を各TextBoxで取得しました MessageBox.Show("SelectedIndexChangedが発生しました") TextBox1.Text = ListBox1.SelectedIndex.ToString If CInt(ListBox1.SelectedIndex) > -1 Then TextBox2.Text = ListBox1.SelectedItem.ToString TextBox3.Text = ListBox1.SelectedValue.ToString TextBox4.Text = ListBox1.Text Else TextBox2.Text = "ヌルです" TextBox3.Text = "ヌルです" TextBox4.Text = "ヌルです" End If 結果は次の通りです。 リストボックスの項目選択時:正常に動作 フォームクローズ時:まずメッセージが表示されて[OK]ボタンでTextBox1には 「-1」と表示されます。その他のTextBoxはエラーが発生するためスルーしています。 以上のことから次のように考えました。 1.メッセージが表示されたのはイベントが発生していることになる 2.SelectedIndexが「-1」となるのはリストボックスの選択がされていない 以上ですが、Jittさんの意見だとフォームクローズ時には、SelectedIndexの変化は ないはずとお考えなのでしょうか。 よろしくお願いいたします。 【追記】 上記の「フォームクローズ時」はフォーム右上の「×」ボタンをクリックしています。 フォームクローズ時にElseに分岐させたのはSelectedValueの値がNullとなってエラーとなるためです。 [ メッセージ編集済み 編集者: だんじり 編集日時 2007-11-02 14:15 ] | ||||||||||||||||
|
投稿日時: 2007-11-02 21:50
げ!見るところ間違ってる。。。
ちゃんと読め>Jitta 失礼いたしました。訂正。
項目がひとつしか選択できないなら、Text プロパティから取って良い、ということです。
少々卑怯なことをしています。 私は「Form を閉じるときに SelectedIndex は変わらない」とは言っていません。 そうではなく、「SelectedIndexChanged が発生するのは SelectedIndex が変わるときだ」としか書いておらず、Form が閉じるときにそうなるかどうかは断定していません。 しかし、その現象を調べるための方法が、だんじりさんの方法では正しくないと書いています。 Form を閉じるときに、何らかの作用で SelectedIndex が変化するなら、変化したというイベントが上がるのは当然です。 それを調べるために、「SelectedIndexChanged イベント ハンドラ内でブレークし、呼び出し履歴を確認する必要があると思います。」と、書いています。 これは憶測ですが、 Form を閉じると、Close から Dispose が(場合によって)呼ばれます。このときに、自身が持っている Control 類を、先に Dipose しているでしょう。 このときに、ListBox.Items から、オブジェクトを削除していると思います。 選択すべきものが無くなるので、当然 SelectedIndex が変化しますよね? これをキャッチしているのではないでしょうか。 他のスレッドでも、「結果をそのまま受け入れるのではなく、結果に至った理由を考える」と書きました。 このスレッドでの結果は、「Form を閉じるときに SelectedIndex が変化する」です。 この結果をそのまま受け入れるのではなく、なぜ変化するのかを調べておけば、後々疑問が出てきたときに、この調査結果から類推することができます。 私は、「憶測ですが」と書いているように、上記の現象を確認しているわけではありません。 しかし、オブジェクトが破棄される順番については、以前に調べたことがあるので、そのことから類推して、ListBox が破棄される直前に、抱えているアイテムから参照を外すため、その時に発生するのではないか、と推測するわけです。 すると、その推測が正しいかどうかを確かめれば、疑問は解決します。 その方法が、「SelectedIndexChanged イベントハンドラ内でブレークし、呼び出し履歴を確認する」ということです。 ここまで書いておいて、VS.NET 2003 C# でプロジェクトを作成してみました。 結果、イベントは発生しませんでした。 だんじりさんの所では発生するのなら、結果が異なります。このことから、結果だけをそのまま受け入れてはいけないと、もう一度書いておきます。 結果を引き起こす環境にも、注意が必要です。 アイテムの追加の方法などが関係していることが考えられます。 私は、Form 上に ListBox をひとつおき、デザイナでアイテムを追加しました。 | ||||||||||||||||
|
投稿日時: 2007-11-03 10:05
Jittaさん、お返事ありがとうございます。
私の質問が悪かったのでしょうか。Jittaさんもおっしゃるように「結果だけをそのまま 受け入れてはいけない」と思い、もともとのSelectedIndexChangedイベントについての 仕様をご存知ならと、以下の質問をしたつもりでした。 1.フォームクローズ時(IndexChangedして)にイベントを発生する。 2.フォームクローズ時(IndexChangedして)にイベントは発生しない。 3.発生の有無は知らないが、イベントの発生はIndexChangedだ。 貴重なテストをしていただきありがとうございました。Jittaさんの意見は3番であった ことが分りました。そしてJittaさんのテスト結果から判断しますと 1.フォームクローズ時はIndexChangedはなくイベントは発生しない。 2.原因は私のPC環境によるものらしい。 ということになりそうですね。ありがとうございました。 私のテストによれれば、まどかさんからご指導いただいた 1.フォームクローズ時、IndexChangedがありイベントを発生する。 となっています。 結果だけを鵜呑みにしないで、これからJittaさんの方法(Form 上に ListBox をひとつ おき、デザイナでアイテムを追加アイテムの追加の方法)と私の方法(テーブルをアイ テムとして設定する方法)について調べてみて、結果を報告します。 Jittaさん、大変ありがとうございました。 | ||||||||||||||||
|
投稿日時: 2007-11-03 11:51
テスト結果を報告します。
テストは新しいプロジェクトを作成して、1個のForm 上に 次のような ListBox1 と ListBox2 を配置し、両方のListBoxにSelectedIndexChangedイベントを設け、 そのイベントハンドラにそれぞれ次のMessageBox のみを記述しました。 1.ListBox1 DataSource: A_BindingSource DisplayMenber:項目名 イベントハンドラ記述→MessageBox.Show("ListBox1_SelectedIndex: " & _ ListBox1.SelectedIndex) 2.ListBox2 デザイナでItems のコレクションにアイテムを記述(シマリス、ニホンリス、ヨーロッパアカリス) イベントハンドラ記述→MessageBox.Show("ListBox2_SelectedIndex: " & _ ListBox2.SelectedIndex) 以上の設定でデバッグしたところ、項目の選択では両方とも正常にSelectedIndex が 表示されました。 続いてフォームを画面右上の「×」で閉じるとListBox1だけが次のように表示され、 ListBox2 のMessageBoxは表示されません。 →「ListBox1_SelectedIndex: -1」 ちなみにListBox2 側のアイテムを ListBoxA_Load時に次のようにItems.Add で設定して 同じテストを行いました。 ListBox2.Items.Add("シマリス") ListBox2.Items.Add("ニホンリス") ListBox2.Items.Add("ヨーロッパアカリス") テスト結果は同じようにフォームを閉じる時はListBox1 のMessageBoxが「-1」と表示され、ListBox2 側は表示されません。 Jittaさんの言われたとおり、アイテムの設定方法によって、フォームを閉じる時の SelectedIndexChangedイベント動作が違っているのかもしれません。 以上、取り急ぎテスト結果を報告しました。 |