リストボックスの選択した行番号を返すには?

解決


のぶ  2008-12-18 23:41:38  No: 145545

VB2008を先日インストールし、VB6でつくったプログラムをコンバージョンしています。Listboxで複数行選択できる設定で、二つ以上マウスで選択したときに、VB6ではListindexで取得できた行番号が、新しいVBでは先頭の選択行を返す様になっており、マウスで選択した行を返してくれません。VB netでも同じ様な現象でしたが、
何か良い方法でもあるのでしょうか?

よろしくお願いします


YuO  2008-12-19 00:40:26  No: 145546

ListBox.SelectedIndices プロパティでしょうか。
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.listbox.selectedindices.aspx


アクア  URL  2008-12-19 00:47:21  No: 145547

アクアと申します。どうぞ宜しくお願いします。

まずListBoxコントロールのSelectionModeプロパティがMultiExtendedかMultiSimpleであるように設定してください。

MultiSimpleの場合はマウスやSpaceキーによる複数行の選択ができますで、今回はこれで検証します。

フォームには
ListBoxコントロール
Buttonコントロール
Labelコントロール
が配置され、ListBoxコントロールのItemsプロパティには既にItemが何個か設定されているものとします。

ButtonコントロールのClickイベントに以下のコードを打ち込んで実行します。

For i As Integer = 0 To ListBox1.SelectedItems.Count - 1
    Label1.Text += Me.ListBox1.SelectedItems(i)
Next

実行したら複数選んで確認してみましょう。
多分うまく選択した複数の項目がLabelコントロールに表示されているはずです。


アクア  URL  2008-12-19 00:53:33  No: 145548

YuOさんの邪魔をしてしまいました申し訳ありません。
また、ご質問では行番号とあったので、私の回答は少し的を外していたようです。申し訳ありません。

なので、
For i As Integer = 0 To ListBox1.SelectedIndices.Count - 1
    Label1.Text += Me.ListBox1.SelectedIndices(i).toString() + ", "
Next

となろうかと思います。


のぶ  2008-12-19 01:57:44  No: 145549

YuO様、アクア様早速のご回答ありがとうございました
ただ、自分がやりたいのは、今現在複数選択は出来る状態です。
それで一個目の選択はたしかにSelectedItems.Count などで取得できるのですが、一個選択してある状態でさらに別の行をマウスで選択したとにの、選択した
クリック行の行番号を知りたいのです。
例えば、10行くらいのリストで、3行目にすでに選択されているとして、
さらに5行目をマウスで選択すると、3行目という返答が返ってきます。
自分としては、今マウスで選択したばかりの5行目という返答がほしいのです。
Label1.Text += Me.ListBox1.SelectedItems(i)  でいうところの
iを返してもらいたいのです。

For i As Integer = 0 To ListBox1.SelectedIndices.Count - 1
    Label1.Text += Me.ListBox1.SelectedIndices(i).toString() + ", "
Next
こちらを使えばたしかに上から順には返してもらえますが、自分は、自分が選択した順に取得したいのです。vb6では Listindex で、取得できたのですが、どうもNET以降そのようなのが見あたらないですね

以上  ご教授  よろしくお願いします。


のぶ  2008-12-19 02:03:53  No: 145550

すみません文法が変でした。削除がないので再度投稿すみません

YuO様、アクア様早速のご回答ありがとうございました
今リストボックスは複数選択は出来る状態です。
それで自分がやりたいのは、一個目の選択はたしかにSelectedItems.Count などで取得できるのですが、一個選択してある状態でさらに別の行をマウスで選択した時に、選択したクリック行の行番号を知りたいのです
例えば、10行くらいのリストで、3行目にすでに選択されているとして、
さらに5行目をマウスで選択すると、上にある3行目という返答が返ってきます。
自分としては、今マウスで選択したばかりの5行目という返答がほしいのです。
Label1.Text += Me.ListBox1.SelectedItems(i)  でいうところの
iを返してもらいたいのです。

For i As Integer = 0 To ListBox1.SelectedIndices.Count - 1
    Label1.Text += Me.ListBox1.SelectedIndices(i).toString() + ", "
Next
こちらを使えばたしかに上から順には返してもらえますが、自分は、自分が選択した順に取得したいのです。vb6では Listindex で、取得できたのですが、どうもNET以降そのようなのが見あたらないですね

以上  ご教授  よろしくお願いします。


我龍院  2008-12-19 06:11:51  No: 145551

書かれている内容に矛盾がありレスがつけ難い状態です。
>例えば、10行くらいのリストで、3行目にすでに選択されているとして、
>さらに5行目をマウスで選択すると、上にある3行目という返答が返ってきます。
>...
>自分が選択した順に取得したいです
選択した順番は3行->5行目なので最初に3行目が返って来て良いのでは。
それとVB6のListindex は現在選択されている行が返ると思うのですが、
それで良ければ、
選択行が複数でも現在選択されている行が知りたい。
の一行で済むと思われますが。


のぶ  2008-12-19 07:59:13  No: 145552

我龍院様  うまく伝えられなくてすみません  上の設定だと順番からいえば3  5とつづきますが、僕がほしいのは選択した順で取得したいので  3行目→5行目の次に4行目をクリックした場合は4行目と返してほしいのです。簡単にいえば、複数選択されている状態で  新たにマウスで別の行を選択したときに  その今選択した行の行番号を返してほしいのです。上の選択順でクリックしていくと  すべて一番先頭の3行目しか返してくれないので  VB6のときのListindexではクリックしたときの行番号をちゃんと返してくれたんですよ^^

以上


YuO  2008-12-19 10:54:43  No: 145553

なってくれないなら作ればいいだけです。

List(Of Integer)にでも前回の選択状況を保持しておいて,
ListBox1.SelectedIndices.OfType(Of Integer).Except(prevList) ' prevListが前回の選択状況
とかやれば取れるのではないでしょうか。


のぶ  2008-12-19 17:52:20  No: 145554

YuO様たびたびありがとうございます。やっぱり前の情報を覚えておいて
次に選択した情報と比較しあるものないものを判定して行うしか無さそうですね
VB6のListindexの様な便利なのがあればと思ったのですが、NETなり2008なりになって、VB6で使えた関数が使えなくなったり、構文などが長くなり初心者の僕にはかなり難しく感じます  汗^^
教えていただいた
ListBox1.SelectedIndices.OfType(Of Integer).Except(prevList)
で一度チャレンジしてみます。
上の文章の意味がまだわからないので、出来た時点でまた報告させていただきます
以上


我龍院  2008-12-19 17:56:02  No: 145555

ListBoxのSelectionModeで微妙に違うが結局はゴリゴリ書くしかないのかな
VB6と同じで良ければIf以下は無くてそのままClickIndex を返せば良い。

    Private Sub ListBox1_SelectedIndexChanged(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
        Console.WriteLine(GetListindex(Me, ListBox1).ToString())
    End Sub

    '選択されていれば行番号を選択されていなければ-1を返す関数
    Public Shared Function GetListindex(ByVal Form As Form, _
                           ByVal ListBox As ListBox) As Integer

        'リストボックスの画面上のY位置
        Dim y As Integer = Form.Top + ListBox.Top + SystemInformation.CaptionHeight

        'リストボックスの選択Itemの位置
        '(マウスのY位置  -  ListBoxの位置)  \  Itemの高さ(整数割り算)
        'ListBox.ItemHeight / 2 は四捨五入を勘案
      Dim ClickIndex As Integer = (Control.MousePosition.Y - _
                             y + ListBox.ItemHeight / 2) \ ListBox.ItemHeight - 1
       
        'Itemが選択されれいるか否か
        If ListBox.SelectedIndices.IndexOf(ClickIndex) >= 0 Then
            Return ClickIndex  '選択されていれば行番号を
        Else
            Return -1          '選択されていなければ0を返す
        End If
    End Function


のぶ  2008-12-19 18:15:42  No: 145556

我龍院様  わざわざ書いて頂いてどうもありがとうございます  
書いて頂いたのは、画面上のマウスの位置から求める方法なんですね
このような考え方はまったく思いつきませんでした^^
こちらの方法でもチャレンジさせて頂きます^^


魔界の仮面弁士  2008-12-19 19:38:01  No: 145557

> マウスの位置から求める方法
リストボックスの選択はキーボードからも行えますので、
SelectedIndexChanged 内でマウス座標に頼るのは危険かと思いますよ。

もし、キーボード操作を除外しても構わないのであれば、
MouseDown イベントを使う事ができるかも知れません。

そしてマウス座標からの取得の場合、項目の高さから位置計算するよりも、
ListBox の IndexFromPoint メソッドを使った方が簡単かと。

  Private Sub ListBox1_MouseDown(…
    Trace.WriteLine(ListBox1.IndexFromPoint(e.Location))
  End Sub

マウス系イベント以外から取得する場合:
  Trace.WriteLine(ListBox1.IndexFromPoint(ListBox1.PointToClient(MousePosition)))


のぶ  2008-12-19 20:22:14  No: 145558

魔界の仮面弁士様  ありがとうございます。
IndexFromPoint ←まさにこれです  画像のポイントの位置から取得
できるというのがVB6でつくったときと考えが違っていたのですが、
リストボックス上のマウス座標の位置からその下の行の番号を
返してくれるんですね^^
また、リストボックス上のマウス座標位置を
List2.PointToClient(MousePosition))これで取得できるということも
勉強になりました^^
我龍院様が書いて頂いたもので最初やってみたところ、一番最初だけ
それらしいのが返ってきたのですが、ビルドとかデバッグを何度かくりかえすたびに
なぜか返ってくる番号がふえていってうまく再現できませんでした。
原因がわからないのですが、どこかでメモリー上でまえのマウス座標位置をおぼえていて増えていったのかそのあたりの原因がわかりませんでした。
YuO様のも試したのですが、これはさっぱりわかりませんでした  すみません
SelectedIndicesの後にOfTypeが見あたらなく、どのように使ったらいいのかがわかりませんでした。もう少し基礎の勉強します汗
この件に関しては、解決できましたので  皆様どうもありがとうございました


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加