ListViewの複数項目削除で再度質問です

このQ&Aのポイント
  • ListViewの複数項目削除で再度質問です。ArrayListのソートの件とListViewのおかしな挙動は解決できたが、削除の部分で再び分からなくなってしまったので質問させて頂く。
  • 複数件のデータ削除を行おうとしたら未整列状態の並びのデータが削除されてしまうという事態が発生してしまった。これはどうすれば解決できるのか。
  • また、複数件の未読既読を制御するのも同様の方法でできるのか。環境はVS2005(C#)、.NET Framework2.0。
回答を見る
  • ベストアンサー

ListViewの複数項目削除で再度質問です

ArrayListのソートの件とListViewのおかしな挙動は解決できたのですが 最初に質問して解決したはずの削除の部分で再び分からなくなって しまったので質問させて頂きます。 今回は本体に今までのコードを正式に組み込んで、動作の確認を 行っていたのですが、複数件(連続や個別選択)のデータ削除を 行おうとしたら意図しないデータ(未整列状態の並びのデータ)が 削除されてしまうという事態が発生してしまいました。 これはどうすれば解決できるのでしょうか? また複数件の未読既読を制御(選択された項目に対してフラグを 入れ替える)するのも同様の方法で出来るのでしょうか? 環境はVS2005(C#)、.NET Framework2.0です。 以下に問題の削除時のコードを載せます。 private void menuDelete_Click(object sender, EventArgs e) { // 選択アイテムが0のときは反応にしない if(listView1.SelectedItems.Count == 0){ return; } if(listView1.Columns[0].Text == "差出人"){ // 受信メールのとき for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { collectionMail[DELETE].Add(collectionMail[RECEIVE][sel_index]); collectionMail[RECEIVE].RemoveAt(sel_index); } } this.textBody.Text = ""; } else if(listView1.Columns[0].Text == "宛先"){ // 送信メールのとき for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { collectionMail[DELETE].Add(collectionMail[SEND][sel_index]); collectionMail[SEND].RemoveAt(sel_index); } } this.textBody.Text = ""; } else if(listView1.Columns[0].Text == "差出人または宛先"){ // 削除メールのとき if(MessageBox.Show("選択されたメールは完全に削除されます。\nよろしいですか?", "確認", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK){ for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { collectionMail[DELETE].RemoveAt(sel_index); } } this.textBody.Text = ""; } } // ツリービューとリストビューの表示を更新する UpdateTreeView(); UpdateListView(); // 選択している位置がリストの件数よりも少ないとき if(currentRow < listView1.Items.Count){ // 選択していた位置-1の行にフォーカスを当て直す listView1.Items[currentRow - 1].Selected = true; listView1.Items[currentRow - 1].Focused = true; listView1.SelectedItems[0].EnsureVisible(); listView1.Select(); listView1.Focus(); } else{ // リストの件数が1以上の時 if(listView1.Items.Count > 0){ // ListViewの行数位置-1の行にフォーカスを当て直す listView1.Items[listView1.Items.Count - 1].Selected = true; listView1.Items[listView1.Items.Count - 1].Focused = true; listView1.SelectedItems[0].EnsureVisible(); listView1.Select(); listView1.Focus(); } } }

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

ListViewのItemsのIndexと collectionMailリストのインデックスが同じ物を指しているかが問題なのでしょう ListからListViewItemを登録する際にListViewItemのTagプロパティにListのインデックスを登録しておきます 削除する際には for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) {   if (listView1.Items[sel_index].Selected) {     int nIndex = (int)listView1.Items[sel_index].Tag     collectionMail[DELETE].Add(collectionMail[RECEIVE][nIndex]);     //collectionMail[RECEIVE].RemoveAt(sel_index);     // 削除済みとして -にしてマークしておく     listView1.Items[sel_index].Tag = -nIndex;     collectionMail[RECEIVE][nIndex].DeleteFlag = true;   } } としてみてはいかがでしょう ArrayListから登録する際にも foreach( Mail mail in list ) {   // フラグをみてリストを追加   if ( !mail.DeleteFlag ) {     ListViewItem Item = new ListViewItem( mail.subject );     Item.SubItems.Add( mail.Address );     // ... その他のデータをついか   } } データをファイルに落とす際に DalateFlagがついてない物だけ書き込むようにする 等の対策でどうでしょう ...

mizuki_sak
質問者

お礼

すみません。 一応この件はもう一度再投稿致します。 やりたい事の半分はできているので次の質問の方で 宜しくお願い致します。

mizuki_sak
質問者

補足

うーん、個人的にはRECEIVEリストから削除して、削除分を DELETEリストに移動するという処理だけで良いと思うのですが・・・。 →元々のプログラムに出来るだけ手を加えないようにしています。 これだと間違った項目を消してしまう可能性があるんですよね。 →何度か試してみて何回か削除するものが異なっていた。 private void menuDelete_Click(object sender, EventArgs e) { // 選択アイテムが0のときは反応にしない if(listView1.SelectedItems.Count == 0){ return; } if(listView1.Columns[0].Text == "差出人"){ // 受信メールのとき for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { // collectionMail[DELETE].Add(collectionMail[RECEIVE][sel_index]); // collectionMail[RECEIVE].RemoveAt(sel_index); int nIndex = (int)listView1.Items[sel_index].Tag; collectionMail[DELETE].Add(collectionMail[RECEIVE][nIndex]); collectionMail[RECEIVE].RemoveAt(nIndex); } } this.textBody.Text = ""; } else if(listView1.Columns[0].Text == "宛先"){ // 送信メールのとき for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { // collectionMail[DELETE].Add(collectionMail[SEND][sel_index]); // collectionMail[SEND].RemoveAt(sel_index); int nIndex = (int)listView1.Items[sel_index].Tag; collectionMail[DELETE].Add(collectionMail[SEND][nIndex]); collectionMail[SEND].RemoveAt(nIndex); } } this.textBody.Text = ""; } else if(listView1.Columns[0].Text == "差出人または宛先"){ // 削除メールのとき if(MessageBox.Show("選択されたメールは完全に削除されます。\nよろしいですか?", "確認", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK){ for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { // collectionMail[DELETE].RemoveAt(sel_index); int nIndex = (int)listView1.Items[sel_index].Tag; collectionMail[DELETE].RemoveAt(nIndex); } } this.textBody.Text = ""; } } // ツリービューとリストビューの表示を更新する UpdateTreeView(); UpdateListView(); // 選択している位置がリストの件数よりも少ないとき if(currentRow < listView1.Items.Count){ // 選択していた位置-1の行にフォーカスを当て直す listView1.Items[currentRow - 1].Selected = true; listView1.Items[currentRow - 1].Focused = true; listView1.SelectedItems[0].EnsureVisible(); listView1.Select(); listView1.Focus(); } else{ // リストの件数が1以上の時 if(listView1.Items.Count > 0){ // ListViewの行数位置-1の行にフォーカスを当て直す listView1.Items[listView1.Items.Count - 1].Selected = true; listView1.Items[listView1.Items.Count - 1].Focused = true; listView1.SelectedItems[0].EnsureVisible(); listView1.Select(); listView1.Focus(); } } }

関連するQ&A

  • ListViewの複数項目削除で意図しない挙動

    前回質問した内容でほとんど複数削除は解決したように 見えたのですが、どういう条件か分からないのですが 複数選択(1件選択の場合は発生しない)して削除ロジックを 実行すると選択している項目と異なる内容の配列(ArrayList)の データを削除してしまうという事が発生します。 これは何が原因で発生しているのでしょうか? またこれの解決法をご教授頂けないでしょうか。 環境はVS2005(C#)、.NET Framework2.0です。 以下に該当部分のコードを載せます。 2000文字を超えてしまったので問題の部分以外は省略しました。 ※添付画像が見にくかったので以下のURLに再掲示しましたので 参考にしてもらえるとありがたいです。 http://angelteatime.punyu.net/questionbox_20090312.jpg 画像では350件ある受信メール(ArrayListに1件ずつMailクラスで 格納されている)の先頭から8件ぐらい選択削除をしようとしている 画面です。 private void menuDelete_Click(object sender, EventArgs e) { // 選択アイテムが0のときは反応にしない if(listView1.SelectedItems.Count == 0){ return; } if(listView1.Columns[0].Text == "差出人"){ // 受信メールのとき for (int sel_index = listView1.Items.Count - 1; sel_index > -1; sel_index--) { if (listView1.Items[sel_index].Selected) { int nIndex = (int)listView1.Items[sel_index].Tag; if (listView1.Items[sel_index].SubItems[1].Text == ((Mail)collectionMail[RECEIVE][nIndex]).subject) { collectionMail[DELETE].Add(collectionMail[RECEIVE][nIndex]); collectionMail[RECEIVE].RemoveAt(nIndex); } else{ MessageBox.Show(string.Format("選択した件名と削除するデータが異なっています。\nリスト位置件名:{0}\n実位置件名:{1}\n(リスト位置:{2}, 実位置:{3}", listView1.Items[sel_index].SubItems[1].Text, ((Mail)collectionMail[RECEIVE][nIndex]).subject, sel_index, nIndex), "エラー", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } } this.textBody.Text = ""; } else if(listView1.Columns[0].Text == "宛先"){ (上記のRECEIVEがSENDに変更のみでロジック変更なし) } else if(listView1.Columns[0].Text == "差出人または宛先"){ (上記のDELETEに変更されDELETEの配列に格納されたデータを削除) } // ツリービューとリストビューの表示を更新する UpdateTreeView(); UpdateListView(); (ListViewのフォーカスを設定し直す) }

  • ListViewとArrayListの連動がうまくいきません

    メールソフトの中で既読、未読を設定するフラグを実装しているのですが ListViewのカラムクリック時の昇順・降順設定を追加するとなぜか おかしな表示になってしまいます。 未読(フラグがtrue)の時は太字で表示されて、既読(フラグがfalse)の 場合は通常のフォントで表示するようにしてあるのですが、 指定している配列ですべてtrueにしているのにもかかわらず表示されるのは trueとfalseの結果の表示がまばらに出てしまって何が原因なのかが 分かりません。 どうすればこれを解決する事が出来るでしょうか? 環境はVS2005(C#)、.NET Framework 2.0です。 リストビューの昇順・降順ロジックはどぼんの.NET Tipsに 載っている文字列、数字、日付で比較が可能なタイプのを 使用しています。 public void UpdateListView() { ArrayList list = null; int i = 0; if (listView1.Columns[1].Text == "差出人") { // 受信メールの場合 list = collectionMail[RECEIVE]; } else if (listView1.Columns[1].Text == "差出人または宛先") { // 削除メールの場合 list = collectionMail[DELETE]; } listView1.BeginUpdate(); // リストビューの内容をクリアする listView1.Items.Clear(); // ListViewを設定する foreach (Mail mail in list) { ListViewItem item = new ListViewItem(mail.subject); item.SubItems.Add(mail.address); item.SubItems.Add(mail.date); // この2行を追加 item.Tag = i; i++; listView1.Items.Add(item); // 未読(未送信)の場合は、フォントを太字にする int index = listView1.Items.Count - 1; if (mail.notReadYet == true) { listView1.Items[index].Font = new Font(this.Font, FontStyle.Bold); } } listView1.EndUpdate(); } private void listView1_DoubleClick(object sender, EventArgs e) { Mail mail = null; ListViewItem item = listView1.SelectedItems[0]; if (listView1.Columns[1].Text == "差出人") { mail = (Mail)collectionMail[RECEIVE][(int)item.Tag]; } else if (listView1.Columns[1].Text == "差出人または宛先") { mail = (Mail)collectionMail[DELETE][(int)item.Tag]; } mail.notReadYet = false; textBox1.Text = mail.body; UpdateListView(); } private void Form1_Load(object sender, EventArgs e) { // ListViewにアイテムを追加する for (int no = 0; no < subject.Length; no++) { Mail mail = new Mail(subject[no], address[no], date[no], body[no], read[no]); collectionMail[RECEIVE].Add(mail); } UpdateTreeView(); UpdateListView(); // ListViewItemComparerの作成と設定 listViewItemSorter = new ListViewItemComparer(); listViewItemSorter.ColumnModes = new ListViewItemComparer.ComparerMode[] { ListViewItemComparer.ComparerMode.String, ListViewItemComparer.ComparerMode.String, ListViewItemComparer.ComparerMode.DateTime }; // ListViewItemSorterを指定する listView1.ListViewItemSorter = listViewItemSorter; }

  • ArrayListの要素削除について

    ArrayListに格納した配列の内容をListViewに表示させているのですが ListViewで複数行選択してその行を削除しようとすると実際に選択して いない行が削除されてしまい、選択した行が削除できません。 また選択を間をあけて選択するとArgumentOutOfRangeExceptionに 引っかかり削除処理が出来ないのですが、どのようにすれば削除が 出来るのでしょうか? 環境はC#(2.0) VS2005です。 以下にソースコードを掲載いたします。 private void Form1_Load(object sender, EventArgs e) { // ListViewにアイテムを追加する for (int no = 0; no < subject.Length; no++) { Mail mail = new Mail(subject[no], address[no]); collectionMail.Add(mail); } // ListViewにcollectionMailの内容を表示 UpdateList(); } private void buttonDelete_Click(object sender, EventArgs e) { foreach (int sel_index in listView1.SelectedIndices) { MessageBox.Show("select no:" + (sel_index + 1), "debug", MessageBoxButtons.OK, MessageBoxIcon.Information); collectionMail.RemoveAt(sel_index); } // ListViewにcollectionMailの内容を表示 UpdateList(); }

  • ファイルコピーで更新日時が変わってしまう。

    XP pro + Visual Basic 2008 で、ファイルをバックアップするためのソフトを作ろうとしています。 ListViewを二つ用意して、それぞれに対象となるフォルダー内のファイルを表示、チェックリストにチェックしたファイルを、互いのフォルダーにコピーする。のようなものを作っています。 しかしListView1からListView2へコピーを行うと、どういうわけか更新日時が数秒づれてコピーされてしまいます。逆の場合はづれが起こらないようです。 原因&解決法を教えてください。 コードは以下の通りです。    Dim i As Integer    Dim response As MsgBoxResult    i = 0    response = MsgBox("リスト1の選択ファイルをコピーしますか?", MsgBoxStyle.YesNoCancel, "確認")    If response = MsgBoxResult.No Then       GoTo CopyRist2    ElseIf response = MsgBoxResult.Cancel Then       Exit Sub    End If    Do Until i >= ListView1.Items.Count       If ListView1.Items(i).Checked = True Then          My.Computer.FileSystem.CopyFile(フォルダ1のパス & "\" & ListView1.Items(i).Text, _             フォルダ2のパス & "\" & ListView1.Items(i).Text, True)          ListView1.Items.RemoveAt(i)       Else          i = i + 1       End If    Loop CopyRist2:    i = 0    response = MsgBox("リスト2の選択ファイルをコピーしますか?", MsgBoxStyle.YesNoCancel, "確認")    If response = MsgBoxResult.No Then       Exit Sub    ElseIf response = MsgBoxResult.Cancel Then       Exit Sub    End If    Do Until i >= ListView2.Items.Count       If ListView2.Items(i).Checked = True Then          My.Computer.FileSystem.CopyFile(フォルダ2のパス & "\" & ListView2.Items(i).Text, _             フォルダ1のパス & "\" & ListView2.Items(i).Text, True)          ListView2.Items.RemoveAt(i)       Else          i = i + 1       End If    Loop 以上です。 よろしくお願いします。

  • VB2010 ListView 使い方

    VB2010でListViewを使っています。かなり順調にプログラムが出来ているのですが、トラブルに遭遇しました。 Form1でDATAを入力して、Form2とForm3でそのDATAをListViewを使って表示しています。 そして、Form2のListViewをForm4に簡素化した雛形にして、ListViewを使って表示させています。 同様に、Form3のListViewをForm5に簡素化した雛形にして、ListViewを使って表示させています。 Form2からForm4は問題なく表示されますが、Form3からForm5はエラーとなります。 エラーは次のところで生じます。 ListView1.Items(2).SubItems.Add(Form3.ListView1.Items(1).SubItems(2)) エラーメッセージは次のようです。 「'1' の InvalidArgument=Value は 'index' に対して有効ではありません。」 また、次のようにコーディングしてみると、 ListView1.Items(2).SubItems.Add(Form3.Label2.Text) 「Labl2」と表示されるだけです。Label2の情報は表示されません。 単純にDATAを移すだけなのに、1つは出来て、もう1つは出来ないというのが分かりません。 どこに問題があるのでしょうか。 かなり悩んでいますが、解決策が見出せません。 ご教授いただける方が居られましたら、宜しくお願い申し上げます。

  • ListViewから選択中の文字列を取得

    VB2005の初心者です。 タイトル通り、ListViewから選択中の文字列によって処理を変えるプログラムを構築しようとしているのですが、うまくいきません。 ComboBoxの場合では Private Sub button1_Click~ If ComboBox1.SelectedItem = "テスト" Then 処理 End if でうまくいったのですが、ListViewの場合では Private Sub button1_Click~ If ListView1.SelectedItems = "テスト" Then 処理 End if と指定すると 「エラー 1 これらの引数で呼び出される、アクセス可能な '=' がないため、オーバーロードの解決に失敗しました」 とエラーがでます。 ListViewから選択中の文字列を取得するには「.SelectedItems」では取得できないのでしょうか? VBに詳しい方ご教授お願いします。

  • ListViewで条件式を使う方法

    Visual Basic 2010でDatasetとListviewを使ってプログラムを作成しています。 DatasetのデータをListviewに表示させるプログラムは下記のコードで完成しました。 ******************************* Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load With ListView1 .Columns.Add("date", 40, HorizontalAlignment.Left) .Columns.Add("no", 40, HorizontalAlignment.Left) .Columns.Add("住所", 100, HorizontalAlignment.Left) showlist() End With End Sub Private Sub showlist() Try 住所TableAdapter.Fill(Kz526DataSet.住所) Catch ex As Exception MessageBox.Show(ex.Message, "住所テーブル") End Try With Kz526DataSet.住所 For i As Integer = 0 To .Rows.Count - 1 ListView1.Items.Add(.Rows(i)("date"), (i)) ListView1.Items(i).SubItems.Add(.Rows(i)("no")) ListView1.Items(i).SubItems.Add(.Rows(i)("住所")) Next End With End Sub ************************************ 次に、Datasetのデータの内一部だけListviewに表示させることにしました。そのため、テキストボックスを設けて、その日付と同じデータをListviewに表示させます。 テキストボックスを設けて、ボタンをクリックしてデータをListviewに表示させようとしたコードです。 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load With ListView1 .Columns.Add("date", 40, HorizontalAlignment.Left) .Columns.Add("no", 40, HorizontalAlignment.Left) .Columns.Add("住所", 100, HorizontalAlignment.Left) showlist() End With End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 住所TableAdapter.Fill(Kz526DataSet.住所) With Kz526DataSet.住所 For c As Integer = 0 To .Rows.Count - 1 If TextBox1.Text = Kz526DataSet.住所.Rows(c)("data") Then ListView1.Items.Add(.Rows(c)("date"), (c)) ListView1.Items(c).SubItems.Add(.Rows(c)("no")) ListView1.Items(c).SubItems.Add(.Rows(c)("住所")) End If Next End With End Sub *************************************** このコードでは、条件式とListViewの関係がいまくいきません。エラーメッセージは次の様に表示されます。 「'3' の InvalidArgument=Value は 'index' に対して有効ではありません。 パラメーター名: index」 いろいろ試行錯誤してみましたところ、「ListView1.Items(c).SubItems.Add(.Rows(c)("no"))」のところで止まります。 if文では、Thenのあとは1行しか書けないのでしょうか。書き方をご指導ください。

  • ListView_DeleteItemの挙動

    リストビューでチェックされた項目を削除したくて下のようなプログラムを書いたのですがうまくいきません どうもListView_DeleteItemに問題があるらしいのは分かるのですが、それ以上のことが分かりません どなたかご教授お願いします index = ListView_GetItemCount(hList); for(i=0;i<index;i++){ if(ListView_GetCheckState(hList,i) != 0){ ListView_DeleteItem(hList,i); } }

  • [VB2008]リストボックス内の複数選択された項目を削除したい

    タイトルの通り、リストボックス内の複数選択された項目を削除したいのですが どうすればいいでしょうか? 下記のコードを組んでみましたが動作しませんでした。 Dim SelectItem As Object Dim ItemList As String = "" For Each SelectItem In Me.ListBox1.SelectedItems Me.ListBox1.Items.Remove(SelectItem.ToString()) Next ご回答お願いします。

  • ArrayListのソートについて

    プログラム上でListViewのカラムをクリックするとソートされる プログラムを作ろうと入れたのですが、リストはソートされるのに 中身(ArrayList)がソートされていないためソート後のアイテムを クリックしても違う値しか出てきません。 それにはArrayListのソートが必要と言う事が書いてあったので 実装をしてみたのですが、比較ができないようなエラーが出て うまくソートもできませんでした。 どうすればListViewのカラムソートと連動してArrayListのソートが 出来るようになるでしょうか? 開発環境はVS2005(C#) .NET2.0です。 サンプルクラスは以下の通りです。 public void UpdateListView() { ArrayList list = null; if (listView1.Columns[1].Text == "差出人") { // 受信メールの場合 list = collectionMail[RECEIVE]; } else if (listView1.Columns[1].Text == "差出人または宛先") { // 削除メールの場合 list = collectionMail[DELETE]; } listView1.BeginUpdate(); // リストビューの内容をクリアする listView1.Items.Clear(); // ListViewを設定する foreach (Mail mail in list) { ListViewItem item = new ListViewItem(mail.subject); item.SubItems.Add(mail.address); listView1.Items.Add(item); } listView1.EndUpdate(); } private void Form1_Load(object sender, EventArgs e) { // ListViewにアイテムを追加する for (int no = 0; no < subject.Length; no++) { Mail mail = new Mail(subject[no], address[no], body[no]); collectionMail[RECEIVE].Add(mail); } UpdateTreeView(); UpdateListView(); } public class Mail { public string subject; public string address; public string body; public Mail(string subject, string address, string body) { this.subject = subject; this.address = address; this.body = body; } }

専門家に質問してみよう