- PR -

ListViewのCheckedItemsが正しく取得できない

1
投稿者投稿内容
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2003-09-22 17:26
初めて投稿させていただきます。

VisualStudio.netを使ってC#でWindowsアプリケーションを作っています。

ListViewクラスのCheckedItemsプロパティはListViewコントロールでチェックされているすべての項目を含むコレクションを返します。
ListViewはCheckBoxesプロパティをtrueにすると各行の左側にチェックボックスが
配置されます。ここでいう「チェックされている」とはそのことです。
ところが以下の操作を行ってもListViewのCheckedItemsが正しく取得できません。


ListViewコントロール(listView1)とButtonコントロール(button1)を配置します。

listView1のCheckBoxesプロパティをtrueにし、ViewプロパティをListにします。

listView1に以下のように3つのListViewItemを追加します。
listView1.Items.Add("1行目");
listView1.Items.Add("2行目");
listView1.Items.Add("3行目");

//button1が押されたときのイベントハンドラを以下のように記述します。
private void button1_Click(object sender, System.EventArgs e)
{
//listView1でチェックされている最初の行のTextを表示する
MessageBox.Show(listView1.CheckedItems[0].Text);
}

実行時に
1、はじめは3行目だけにチェックしてbutton1を押す
→メッセージボックスで「3行目」と表示される
2、次に1行目だけにチェックしてbutton1を押す
→メッセージボックスで「3行目」と表示される

1行目だけにチェックしているのに「3行目」と出てしまいます。

このことに関して何かおわかりの方、ご教授願います。

環境は WindowsXP pro、Visual Studio.net 2002です。
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2003-09-22 18:07
自己レスです。

ちなみに、イベントハンドラの部分を以下のようにすると

private void button1_Click(object sender, System.EventArgs e)
{
  for(int i=0;i<listView1.CheckedItems.Count;i++)
  {
    MessageBox.Show(listView1.CheckedItems[i].Text);
  }
}

実行時
1、最初は1行目と2行目にチェックしてbuttun1を押す
→「1行目」「2行目」の順でメッセージボックスが表示される
2、次に2行目と3行目にチェックしてbuttun1を押す
→「2行目」「3行目」の順でメッセージボックスが表示される

のように正常です。

しかし、
1、最初は3行目だけにチェックしてbuttun1を押す
→メッセージボックスで「3行目」と表示される
2、次に1行目と2行目にチェックしてbuttun1を押す
→メッセージボックスで「3行目」と表示されたあと
for文の2週目で「指定された引数は、有効な値の範囲内にありません。」
のエラーになります。

3行目だけにチェックした場合も、1行目と2行目にチェックした場合も
listView1.CheckedItems.Countの値は正しく取得できています。

また、foreach文で代用するとなぜか正常に動作します。

[ メッセージ編集済み 編集者: べる 編集日時 2003-09-22 18:08 ]
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2003-09-25 18:14
また自己レスです。

以下の冒頭で紹介されていた逆コンパイラを使ってライブラリの中を見てみました。
http://www.atmarkit.co.jp/fdotnet/tools/dotfuscator/dotfuscator_02.html

CheckedItems[n] は内部的に CheckedIndices[n] を参照しています。
ListView.CheckedIndexCollection (CheckedIndicesの戻り値クラス) の
インデクサ ( get_Item(int index) ) を見てみると以下のようになっています。

public int get_Item(int index)
{
 int num1;
 int num2;
 ListViewItem item1;
 if (index < 0)
 {
  throw new ArgumentOutOfRangeException("index");
 }
 if ((this.lastIndex == -1) || (index < this.lastIndex))
 {
  this.lastItemIndex = 0;
  this.lastIndex = 0;
 }
 else
 {
  if (index == this.lastIndex)
  {
   return this.lastItemIndex;
  }
 }
 num1 = this.owner.Items.Count;
 for (num2 = this.lastItemIndex; (num2 < num1); num2 = (num2 + 1))
 {
  item1 = this.owner.Items[num2];
  if (item1.Checked)
  {
   if (this.lastIndex == index)
   {
    this.lastItemIndex = num2;
    return num2;
   }
   this.lastIndex = (this.lastIndex + 1);
  }
 }
 throw new ArgumentOutOfRangeException("index");
}


lastIndex、lastItemIndex はCheckedIndexCollection のメンバ変数で共に CheckedIndexCollection のコンストラクタで-1 に設定されているようです。
1回目と2回目のボタン押下(1回目と2回目のCheckedItems呼び出し)で同じ
CheckedIndexCollectionインスタンスを参照しているなら(推測ですが)、
当然、おかしなこと(1回目の投稿に書いたこと)は起こります(上のget_Itemを
少し調べてみるとわかります)。

これはライブラリのバグではないのでしょうか。
1

スキルアップ/キャリアアップ(JOB@IT)