2024年10月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
無料ブログはココログ

 

« あけましておめでとうございます | トップページ | 小吉・・・ »

2010年1月 2日 (土)

仮想ListViewでCheckBoxを使う方法

和魂の表示をListViewにしたら、表示件数が多くなると更新のたびにハングするようになる。
これはListViewでリソースを追加する毎に描画しなおす所為らしい。
これを回避するには仮想リストビューにする。
仮想リストビューとはどういったモノかというと、ListViewは表示だけ行い、表示する項目の管理はプログラムで行うというもの。
VirtualListSizeに表示項目数を指定して、表示する項目はRetrieveVirtualItemイベントで渡す。このイベントで表示する項目のIndexを渡されるので、それに対してListViewItemオブジェクトを渡せばいい。
それだけ。

仮想リストビューは表示項目を管理しないのでItems、CheckedItems、SelectedItemsプロパティは使用できない。アクセスすると例外が発生するので、通常のListViewと同じようにしてはいけない。選択項目はSelectedIndicesプロパティで位置のリストを取得する事ができる。

ここから本題。
和魂ではCheckBoxを使用するのだけれど、仮想ListViewにしてCheckBoxの設定位置を取ろうとCheckedIndicesプロパティにある設定数を取得しようとしても例外が発生してしまう。MSDNに使えると書いているのに・・・。
どうしてかと悩んでふと表示されているリストビューを見てみるとCheckBoxが表示されていない!
んで、ちょっと検索してみたら、「THE CODE PROJECT」の”ListView in VirtualMode and checkboxes”というドンぴしゃな記事があった。

試してみた。
これが

Listview_vertualmode

こうなる。

Listview_vertualmode2

残念ながらCheckedIndicesプロパティは使えないみたい。
なのでListView.ItemsのCheckedプロパティをなめていくしかないみたいだ。

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

namespace ListViewTEST1
{
    public partial class Form1 : Form
    {
        ListViewItem[] item_;
       
        public Form1()
        {
            InitializeComponent();

            button1.Click += new System.EventHandler(this.button1_Click);

            listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            new System.Windows.Forms.ColumnHeader(),
            new System.Windows.Forms.ColumnHeader()});

            listView1.CheckBoxes = true;
            listView1.VirtualMode = true;
            listView1.View = View.Details;
            listView1.RetrieveVirtualItem += new System.Windows.Forms.RetrieveVirtualItemEventHandler(this.listView1_RetrieveVirtualItem);
            listView1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.listView1_MouseClick);

            listView2.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
            new System.Windows.Forms.ColumnHeader(),
            new System.Windows.Forms.ColumnHeader()});

            listView2.CheckBoxes = true;
            listView2.VirtualMode = false;
            listView2.View = View.Details;
            
            item_ = new ListViewItem[10000];

            for (int index = 0; 10000 > index; index++)
            {
                item_[index] = new ListViewItem(new string[] { index.ToString(), "test" + index.ToString() });
                item_[index].Checked = true;
                item_[index].Checked = false;
                listView2.Items.Add(item_[index]);
            }

            listView1.VirtualListSize = 10000;
        }

        private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            Trace.WriteLine("RetrieveVirtualItem "+ e.ItemIndex.ToString());
            e.Item = item_[e.ItemIndex];
            e.Item.Name = e.ItemIndex.ToString();
        }

        private void listView1_MouseClick(object sender, MouseEventArgs e)
        {
            ListView lv = (ListView)sender;
            ListViewItem lvi = lv.GetItemAt(e.X, e.Y);
            if (lvi != null)
            {
                if (e.X < (lvi.Bounds.Left + 16))
                {
                    lvi.Checked = !lvi.Checked;
                    lv.Invalidate(lvi.Bounds);
                }
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show(listView1.Items[0].Checked.ToString()); // OK
            //MessageBox.Show(listView1.CheckedIndices.Count.ToString()); // NG

        }
    }
}

« あけましておめでとうございます | トップページ | 小吉・・・ »

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: 仮想ListViewでCheckBoxを使う方法:

« あけましておめでとうございます | トップページ | 小吉・・・ »