ListView の仮想リストビューを用いる - VirtualListView, VirtualMode の利用 - C#

ListViewで仮想リストビューを利用するコードを紹介します。

UI

Windows Formアプリケーションを作成し下図のUIを作成します。ListView, ImageListを配置します。

ImageListのプロパティ設定

ImageListのプロパティを設定します。"ColorDepth"を"Depth32Bit"に設定します。


ImageListのImagesプロパティにアイコンを追加します。

ListViewのプロパティ設定

ListViewのVirtualModeプロパティをTrueに設定します。"VirtualMode"プロパティをTrueにすることでListViewが仮想リストビューのモードになります。また、LargeImageListプロパティにフォームに追加したImageList(今回のアプリの場合はimageList1)を設定します。


ListViewのRetrieveVirtualItemイベントを実装します。(コードは下記です)

コード

以下のコードを記述します。

FormMain.cs

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;

namespace ListViewDemo
{
  public partial class FormVirtualListView : Form
  {
    List<ItemInfo> dataList = new List<ItemInfo>();


    public FormVirtualListView()
    {
      InitializeComponent();
    }

    private void FormVirtualListView_Load(object sender, EventArgs e)
    {
      ItemInfo ii;

      ii = new ItemInfo();
      ii.Name = "ペンギン";
      ii.Address = "南極";
      ii.Age = 3;
      ii.ImageIndex = 0;
      dataList.Add(ii);

      ii = new ItemInfo();
      ii.Name = "にわとり";
      ii.Address = "養鶏所";
      ii.Age = 1;
      ii.ImageIndex = 1;
      dataList.Add(ii);

      ii = new ItemInfo();
      ii.Name = "ブタ";
      ii.Address = "養豚所";
      ii.Age = 2;
      ii.ImageIndex = 2;
      dataList.Add(ii);

      ii = new ItemInfo();
      ii.Name = "クジラ";
      ii.Address = "太平洋";
      ii.Age = 20;
      ii.ImageIndex = 3;
      dataList.Add(ii);

      listView1.VirtualListSize = dataList.Count;
    }

    private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
    {
      if (e.ItemIndex < dataList.Count) {
        if (e.Item == null) {
          e.Item = new ListViewItem();
        }

        e.Item.ImageIndex = dataList[e.ItemIndex].ImageIndex;
        e.Item.Text = string.Format("{0:s}", dataList[e.ItemIndex].Name);
      }
    }
  }
}

解説

ItemInfo型のList(dataList)を作成し、このリストにリストビューに表示する情報を格納します。Listへのデータの挿入はLoadイベントで実行されます。また、LoadイベントではListView.VirtualListSizeプロパティを設定しています。このプロパティは仮想リストビューを用いた場合のアイテムの個数を指定するプロパティです。今回のプログラムではdataListの要素をListViewに表示するためVirtualListSizeにはdataListの要素数(Count)を設定しています。

仮想リストビューの場合はアイテムの描画が必要な場合にはRetrieveVirtualItemイベントが呼び出されます。RetrieveVirtualItemイベントの引数"RetrieveVirtualItemEventArgs"のItemが描画すべきリストビューのアイテムになります。アイテムのインスタンスを作成しキャプションとイメージインデックスを設定しています。

ItemInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ListViewDemo
{
  public class ItemInfo
  {
    public string Name;
    public string Address;
    public int Age;

    public int ImageIndex;
  }
}

解説

ItemInfoクラスはリストビューに追加する要素の情報を格納するクラスです。

実行結果

プロジェクトを実行します。リストビューにアイテムが表示されます。

補足 (リストビューで View=Details を用いる場合)

リストビューのViewプロパティを"Details"に変更します。


Columnsプロパティを編集します。今回Columnを3つ追加しました。


デザイナの外観は下図になります。ListViewにColumnが表示されています。

コード

コードは以下になります。
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;

namespace ListViewDemo
{
  public partial class FormVirtualListView : Form
  {
    List<ItemInfo> dataList = new List<ItemInfo>();


    public FormVirtualListView()
    {
      InitializeComponent();
    }

    private void FormVirtualListView_Load(object sender, EventArgs e)
    {
      ItemInfo ii;

      ii = new ItemInfo();
      ii.Name = "ペンギン";
      ii.Address = "南極";
      ii.Age = 3;
      ii.ImageIndex = 0;
      dataList.Add(ii);

      ii = new ItemInfo();
      ii.Name = "にわとり";
      ii.Address = "養鶏所";
      ii.Age = 1;
      ii.ImageIndex = 1;
      dataList.Add(ii);

      ii = new ItemInfo();
      ii.Name = "ブタ";
      ii.Address = "養豚所";
      ii.Age = 2;
      ii.ImageIndex = 2;
      dataList.Add(ii);

      ii = new ItemInfo();
      ii.Name = "クジラ";
      ii.Address = "太平洋";
      ii.Age = 20;
      ii.ImageIndex = 3;
      dataList.Add(ii);


      listView1.VirtualListSize = dataList.Count;

    }

    private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
    {
      if (e.ItemIndex < dataList.Count) {
        if (e.Item == null) {
          e.Item = new ListViewItem();
        }

        e.Item.ImageIndex = dataList[e.ItemIndex].ImageIndex;
        e.Item.Text = string.Format("{0:s}", dataList[e.ItemIndex].Name);
        e.Item.SubItems.Add(string.Format("{0:s}", dataList[e.ItemIndex].Address));
        e.Item.SubItems.Add(string.Format("{0:d}", dataList[e.ItemIndex].Age));
      }
    }

  }
}

実行結果

実行結果は下図になります。正しく情報がリストビューに表示されています。

仮想リストビューを使うメリット

仮想リストビューを使うメリットは以下があります。

リストビューの要素数が非常に多い場合

リストビューの要素の個数が非常に多い場合、通常モードではすべてのListViewのItemの要素に対してListViewItemオブジェクトを用意する必要があります。そのため多くのメモリを消費します。また、初期化時にすべての要素に対してListViewItemオブジェクトを準備するため動作速度の低下も起こります。仮想リストビューの場合画面に表示される部分の要素だけListViewItemオブジェクトを用意するため、動作速度の低下やメモリの消費量が少なくて済みます。

情報が分散しない

今回の例のようにList<ItemInfo>リストの要素をリストビューに表示する場合、通常のモードではListViewItemオブジェクトを生成するため、リストビューに表示するキャプションやアイコンのインデックス番号はListViewItemに設定し、内部で持つ情報はItemInfoクラスに格納されます。そのため、どちらかの値が変更された場合は値の変更を双方に反映する必要があります。一方仮想リストビューを用いた場合はアイテムのキャプションやアイコンのインデックスなどリストビュー表示に関する情報もItemInfoオブジェクトに格納されるためすべての情報をItemInfoに集約できます。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2013-06-06
iPentec all rights reserverd.