DOBON.NET DOBON.NETプログラミング掲示板過去ログ

ListViewで複数行選択時のItemCheckイベントでは

環境/言語:[WindowsXP,C#,NET Framework1.0]
分類:[.NET]

2005/05/23(Mon) 18:03:18 編集(投稿者)

お世話になります。にゃおと申します。

ListViewのItemCheckイベントで、チェックされたレコードのある列の集計を行っています。
(チェック→内部変数にプラス、チャック解除→内部変数にマイナス)
この目的から、レコード毎に1回だけ処理を行いたいのですが、

複数行選択時のItemCheckイベントではレコード毎に3回飛んできます。
検証コード↓
private void listView1_ItemCheck(object sender, System.Windows.Forms.ItemCheckEventArgs e)
{
Debug.WriteLine(String.Format("listView1_ItemCheck:Index[{0}]", e.Index));
}

回避案
 1.ItemCheckイベントの最初の一回だけを取得し、forで選択されたレコードで処理を行う
 2.3回→1回にする
思いつくのはこの2つなんですが、対応するための方法の検討がつきません。

よろしくお願い致します。
[VB.NET]使いなので下記コードで試験しました。
…が、現象を再現できませんでした。他のコードに
原因があるのでは?
[コード]
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim wItem As ListViewItem
Dim i, j, wColCount As Integer

With Me.ListView1
.View = View.Details
'.FullRowSelect = True
.MultiSelect = True
.CheckBoxes = True
With .Columns
.Clear()
.Add("A", 50, HorizontalAlignment.Left)
.Add("B", 50, HorizontalAlignment.Left)
.Add("C", 50, HorizontalAlignment.Left)
wColCount = .Count
End With
With .Items
.Clear()
For i = 0 To 5
wItem = .Add(CStr(i) & ",0")
With wItem.SubItems
For j = 1 To wColCount - 1
.Add(CStr(i) & "," & CStr(j))
Next
End With
Next
End With
End With
End Sub

Private Sub ListView1_ItemCheck(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemCheckEventArgs) Handles ListView1.ItemCheck
Debug.WriteLine(String.Format("listView1_ItemCheck:Index[{0}]", e.Index))
End Sub

[テスト方法]
1,3,4,5行を選択状態でチェックボックスクリック。
[出力]
listView1_ItemCheck:Index[1]
listView1_ItemCheck:Index[3]
listView1_ItemCheck:Index[4]
listView1_ItemCheck:Index[5]
[結果]
レコード毎に1回のイベントしか起こってないため問題なし。
るしぇさん回答ありがとうございます。

> …が、現象を再現できませんでした。他のコードに
> 原因があるのでは?
るしぇさんに提示して頂いたソースと同じことをC#、VB.NET確認してみましたが、
現象は発生しました。(デザイナでデータを作成したので、全く同じではありませんが)

それと自分はNET Framework1.0を使用しています。
るしぇさんの環境は1.1でしょうか?

よろしくお願い致します。
原因が少しわかった感じです。

NET Framework1.0と1.1でListViewのOnItemCheckの実装が違うようです。
IL DASM及びReflector for .NETで確認しました。
対応後また報告します。

以上、よろしくお願い致します
>るしぇさんの環境は1.1でしょうか?
はい、1.1です。
>NET Framework1.0と1.1でListViewのOnItemCheckの実装が違うようです。
http://www.microsoft.com/japan/msdn/netframework/changeinfo/Backwards1.0to1.1/default.asp
とかにそれらしい記述もないですし、サラッとバグ直しましたっぽい…臭いなぁ(^^;)

…で、1.0のまま開発する必要があるんですか?…まぁ、ItemCheck イベントは連続して
起こるでしょうから、何かコレクションに格納していって、タイマーイベントなんかを
使って ItemCheck イベントが全て処理された後に処理するとか…。

データベースの更新が関係してるなら、不安定な ItemCheck イベントは使わず、
更新ボタンを別に用意して、ボタン押下で処理するとかの方が良いでしょう。
…ただ単にリストのチェック項目の数をリアルタイム表示させたいのなら…うーん。
……タイマーイベントくらいしか思い浮かばない(;▽;)
LisViewの派生クラスでOnItemCheckをオーバライドし、
ここで独自イベントを発行することで対応しました。

OnItemCheckには正常にイベントが飛んでくるので、
独自イベントを使用しないで、目的のコードを直接実装することもできたのですが、
そうすると既存部分を修正する必要があったので独自イベントを使用しました。

↓がコードです。
public event ItemCheckEventHandler ItemCheckEx;
protected override void OnItemCheck(ItemCheckEventArgs ice)
{
if (ice.Index < this.Items.Count && this.ItemCheckEx != null)
{
this.ItemCheckEx(this, ice);
}
}

一応、問題ないように見えます。
(まだ、イベントとかデリゲートよく理解していないんですよ)

以上、解決しました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板