VB.NetでListViewを使いたいのですが、実行したときに選択されている項目(行)の番号を取得したいのですが、わかりません。
ListBox(VB6の)にはIndexというプロパティがあったと思うのですが、そのように選択されている番号は簡単に取得できないのでしょうか?
ListView1.SelectedItems(i).Index
で i を0から順にカウントすれば取れると思うよ。…というか VB6.0 で作ったプログラムがあれば .Net で開けば変換してくれます。それを参考にするのも手です。
助言ありがとうございます。VB6で使っていたのはListBoxでした。VB.Netへの変換後は【ListBox.SelectedIndex】となっていました。
教えていただいた通りに試してみましたが、どうもうまくいきません。【.SelectedItems(i)】の【i】がなんだかわかりません。ヘルプで見ると項目のインデックスとしかでていないのですが・・・。
下記の記述で実行すると一回目のリストのクリック時は番号を取得できるのですが、連続で違う行を選択すると【引数が有効な値の範囲内にありません】となり終了してしまいます。
Private Sub Listview_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Listview.SelectedIndexChanged
Dim SelectNo As Integer
SelectNo = Listview.SelectedItems(0).Index
TextBox1.Text = SelectNo
End Sub
あっ、すいません。「使っていたのはListBoxでした」というのはVB6のときのコントロールです。VB.Netでは【ListView】を使用しています。
SelectedIndexChanged は選択行が変更されると毎回走ります。
人間には選択行を1行目から2行目に変えたように見えても
プログラム側から見ると
・1行目を選択
・SelectedIndexChanged
・1行目を選択解除(選択行なし)
・SelectedIndexChanged←上記のプログラムではここでエラー
・2行目を選択
・SelectedIndexChanged
という処理になります。ちゃんとデバッグすれば分かりますよ?。
せっかく Index をヘルプで調べたんならもう一歩! Listview が
どんなオブジェクトを格納してそのプロパティには何がどんな形で
あるか…そこまで調べられればすぐに理解できますよ。
明日、時間があれば上手くいくソース載せます。それまで頑張ってみて?
イベントハンドラを【Handles Listview.Click】にしたら取得することができました。なぜ。【.SelectedItems(i)】のインデックスを0にしないといけないのかがいまだにわかっていないので、もう少し勉強します。
ありがとうございました。
'一応書いたので参考にしてもらえれば嬉しいです。
' ポイント1:文頭に Option Explicit On 宣言をしファイル内のすべての変数を明示的に宣言するクセをつけましょう。
' ポイント2:キャストしなくても .NET が適当に変換してくれますが、変数は明示的にキャストするクセをつけましょう。
' ポイント3:プロパティ名にも意味があります。ListView は Item を加えて ListView.Items(i).Text を表示します。
' ListView.Items の最後に複数形の s がついてるのは ListView.Items が Item を複数抱え込んだコレクション
' だからです。ListView.SelectedItems も同じで選択行を全て抱え込んだコレクションです。デバッグ時に内容を
' 知りたい場合はウォッチ式を追加し、ツリーを展開してください。
Private Sub ListView_SelectedIndexChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles ListView.SelectedIndexChanged
Dim SelectNoTxt As String
Dim i As Integer
With Me.ListView
' ListView に Item(項目) が1つもない場合処理しない。
If .Items.Count = 0 Then Exit Sub
' ListView で SelectedItem(選択された項目) が1つもない場合
' (1行も選択されていない場合)選択行についての処理を飛ばします。
With .SelectedItems
If .Count <> 0 Then
For i = 0 To .Count - 1
' カウントが0始まりか1始まりか?そして終了条件は極めて重要です。
' 配列などを扱う時や、エクセルのセル選択など…つねに意識しましょう。
'''SelectNoTxt = SelectNoTxt & CStr(Me.ListView.SelectedItems(i).Index + 1) & ", "
' 上のように書けますが、With を使ってますので下のように書き直します。
' SelectedItems も Item のコレクションなので以下のように書けます。
SelectNoTxt = SelectNoTxt & CStr(.Item(i).Index + 1) & ", "
Next i
End If
End With
' この時点で SelectNoTxt の長さが0の場合、行は選択されていません。
' If 文の条件は SelectNoTxt = "" としても同じです。
' SelectNoTxt の明示的な初期化(SelectNoTxt = "")は行っていませんが、SelectNoTxt の
' スコープは関数内のみ有効なので、関数を抜けると破棄されます。(再び関数が呼ばれた時に
' "" で初期化されます)
If Len(SelectNoTxt) = 0 Then
' 行が選択されていない状態は、ユーザが ListView の微妙な位置を選択した場合や、
' Esc キーを押下した時(今回は ListView_KeyPress イベントで意図的に定義)に起こります。
SelectNoTxt = "行は選択されていません。"
Else
SelectNoTxt = SelectNoTxt & "行を選択しましたね?(‾ー‾)。"
End If
' TextBox1 に表示
TextBox1.Text = SelectNoTxt
End With
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
' 初期化処理
InitForm()
End Sub
' 初期化処理
Private Sub InitForm()
' i,j,m,n などは通常、カウンタとして使われます。
' 何の説明もなくても使用されている場所を見てカウンタなら
' Dim i, j, m, n As Integer と宣言しましょう。
Dim i As Integer
' ListView のプロパティを設定([デザイン]画面で設定しても同じです)
With Me.ListView
.Columns.Clear() ' カラムの初期化
.Items.Clear() ' Item の初期化
.Columns.Add("名称", .Width - 5, HorizontalAlignment.Left) ' カラムの設定
.HeaderStyle = ColumnHeaderStyle.Nonclickable ' カラムはボタン状でない表示
.MultiSelect = True ' 複数行選択可(Ctrl[or Shift]キーを押したまま選択)
.View = View.Details ' 詳細表示
For i = 1 To 7 ' テスト表示用 Item 追加
.Items.Add("Test" & CStr(i))
Next i
End With
' ちょっとした初期化のテクニック(関数内で引数を利用してないのでエラーは起こらない)
ListView_SelectedIndexChanged(Nothing, Nothing)
End Sub
Private Sub ListView_KeyPress(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyPressEventArgs) _
Handles ListView.KeyPress
Dim i As Integer
'Debug.WriteLine(CStr(Asc(e.KeyChar))) ' キーの文字コードを簡単に出力する方法
With Me.ListView
Select Case e.KeyChar
Case Chr(27) ' Esc キー押下で全ての行の選択解除
With Me.ListView
If .SelectedItems.Count = 0 Then Exit Sub
' 何でカウンタを逆に回してるかは自分で色々変更して検証してください。
For i = .SelectedItems.Count - 1 To 0 Step -1
.Items(.SelectedItems(i).Index).Selected = False
Next i
End With
Case Else
End Select
End With
End Sub
ListBoxで同じようなことは出来ないのでしょうか?
ツイート | ![]() |