【C#.NET】ListViewで選択しているインデックスを取得する

C#
スポンサーリンク
スポンサーリンク

はじめに

この記事は昔のブログからの移設記事です。

今のVisual Studio用にリメイクしておりますが、古い情報があった場合は申し訳ありません。

上記承諾いただけましたら続きをどうぞ!

 

ListViewのインデックス番号取得

 

問題

C#のFormを作成しているときに、csvを読み込んで、その値をListViewに入れ込むプログラムを作りたくなりました。

csvで出力しているログを解析して可視化したかったのです。

なんでjsonとかxmlとかじゃないの?って言われると困りますが。。。

 

んで、ListViewにデータを入れて、選択したIndex番号を取得してそのカラムのデータを色々ごちゃごちゃしようと思い、まずは選択したIndex番号を取ろうと思ったのですが、ここであることに気づきました。

SelectedIndexプロパティがない

ListBox等であればインデックス番号を取得する際にはSelectedIndexを使うのですが、ListViewにはそれがありません。

 

解決方法

ListViewにはSelectedIndexがないのですが、代わりにSelectedItemsの中にIndexプロパティが用意されております。

これでSelectedIndexの代替をするわけですね。

というわけで軽く検証用に書いてみました。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ListViewTestProject
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            lv_main.View = View.Details;

            lv_main.Columns.Add("Column1");
            lv_main.Columns.Add("Column2");
            lv_main.Columns.Add("Column3");

            ListViewItem lvi;

            lvi = lv_main.Items.Add("item1-1");
            lvi.SubItems.Add("item1-2");
            lvi.SubItems.Add("item1-3");

            lvi = lv_main.Items.Add("item2-1");
            lvi.SubItems.Add("item2-2");
            lvi.SubItems.Add("item2-3");

            lvi = lv_main.Items.Add("item3-1");
            lvi.SubItems.Add("item3-2");
            lvi.SubItems.Add("item3-3");
        }

        private void lv_main_SelectedIndexChanged(object sender, EventArgs e)
        {
            int idx = 0;
            idx = lv_main.SelectedItems[0].Index;
            label1.Text = (idx + 1).ToString() + "番目が選択されました。";
        }
    }
}

 

実行するとこんな感じ。

 

では実際に選択してみましょう。

おーいい感じ。

ではこのまま2つ目も選択しましょう

デデーン!

例外が発生してアプリケーションが強制的に終了されました。

 

問題その2

1つ目のインデックスを選択したあと、続けて2つ目を選択すると、なぜか例外エラーを吐きすててアプリがお亡くなりになりました。

ArgumentOutOfRangeException はハンドルされませんでした。
‘0’ の InvalidArgument=Value は ‘index’ に対して有効ではありません。
パラメーター名: index

例外エラーのメッセージを見てみると、どうやらindexというパラメータに0が入ってしまったからのようです。

んで調べてみると、どうやらListViewのインデックスを選択しなおした際、現在選択されている項目数)が一時的に0以下になってしまうそうです。

そのせいで「lv_main.SelectedItems[0].Index;」の部分で挙動がおかしくなってしまったのでしょう。

 

解決方法その2

原因が分かったので、エラー発生条件をつぶしてしまいましょう。

インデックスを選択している項目数(lv_main.SelectedItems.Count)が0以下になるのがいけないのですから、0以下になる際には処理をしないように条件を書いてあげればOKです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ListViewTestProject
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();

            lv_main.View = View.Details;

            lv_main.Columns.Add("Column1");
            lv_main.Columns.Add("Column2");
            lv_main.Columns.Add("Column3");

            ListViewItem lvi;

            lvi = lv_main.Items.Add("item1-1");
            lvi.SubItems.Add("item1-2");
            lvi.SubItems.Add("item1-3");

            lvi = lv_main.Items.Add("item2-1");
            lvi.SubItems.Add("item2-2");
            lvi.SubItems.Add("item2-3");

            lvi = lv_main.Items.Add("item3-1");
            lvi.SubItems.Add("item3-2");
            lvi.SubItems.Add("item3-3");
        }

        private void lv_main_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lv_main.SelectedItems.Count > 0)
            {
                int idx = 0;
                idx = lv_main.SelectedItems[0].Index;
                label1.Text = (idx + 1).ToString() + "番目が選択されました。";
            }
        }
    }
}

というわけで実行!

無事、2つ目を選択しても正常に処理されました!

ちなみに、try-catchで例外対策してもよかです。

try-cacheで書くとこんな感じ(必要以外の部分は端折ります)

        private void lv_main_SelectedIndexChanged(object sender, EventArgs e)
        {
            int idx = 0;
            try
            {
                idx = lv_main.SelectedItems[0].Index;
                label1.Text = (idx + 1).ToString() + "番目が選択されました。";
            }
            catch (ArgumentOutOfRangeException)
            {
                label1.Text = "エラー!";
            }
        }

基本的にはtry-cacheでの例外処理はifで処理するよりもリソースを多く使う傾向があるらしいので、簡単なものであればifで例外対策してしまったほうがいいでしょう。

 

まとめ

というわけでまとめます。

・ListViewを使ってインデックス番号をとるときはSelectedItems[n].Indexを使おう

・でも、例外対策はきっちりとね

以上でした。

それでは!

 

参考

【C#.NET】ListViewの選択しているインデックスを取得する

※というか、自分の古いブログからの転載です。

 

基礎からしっかり学ぶC#の教科書 C# 7対応 [ WINGSプロジェクト 高江 賢 ]
created by Rinker

 

 

コメント

タイトルとURLをコピーしました