C# ListViewに画像データを表示する

C# listView画像表示

 C#フォームアプリ―ケーションで画像データを扱う際に出来るだけ視覚的に表示したいと思い調査しました。
「.NET TIPS:ListViewコントロールでサムネイル画像を一覧表示するには?」(https://www.atmarkit.co.jp/ait/articles/0508/12/news091.html)というサイトに指定フォルダの画像ファイルをlistViewコントロールに表示する方法が書かれていましたので、そのまま利用させて頂くと、見事に元画像をサムネイル画像に変換し、listView表示してくれました。
 ただ、画像表示順を変更したいなど、個人要望を反映しようとすると、追加調査が必要となり、確認した内容をまとめておきます。

listViewとimageListの関係

 今回、listViewにサムネイル画像を表示する為に、listViewの他にimageListを用意しています。今回の場合、listView.LargeImageListプロパティにimageListをデータソースとして指定していますが、個々のリスト項目の表示画像指定がされているのか判らず確認しました。
 個人理解ですが、下図の通り、listViewとimageListにはイメージインデックス番号とイメージキー(文字列)があり、いずれかをリスト項目と画像の紐付けに使用します。imageListに画像登録時は、イメージインデックス番号は、順番に自動付与される様です。

 尚、上の図の注記に“①listViewインデックス(表示順)”と書きましたが、データ項目を挿入(insert)した場合に表示される画像は最後に追加され、インデックス番号と一致しませんでしたので、訂正しておきます。

 イメージインデックス番号とイメージキー(文字列)による紐付け方法をテストプログラムを作成し確認しました。下図[1]~[10]の番号表示部分が結果です。紐付け方法は違いますが、同じ結果になっています。
(上段:イメージキーによる紐付,下段:インデックス番号による紐付)

 画像表示後、関連するプロパティが、どの様になっているか、リストボックスに出力し確認しました。
上段(listView1)はイメージインデックス、下段(listView2)はイメージキーが設定されていません。imageList側には、イメージインデックス、キーとも設定され、どちらからも紐付け出来る状態です。


以下、今回のテストプログラムです。

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

using System.IO;

namespace ListViewTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            listView_init();
            get_pic_thumbnail();
        }

        private void listView_init() {
            listView1.LargeImageList = imageList1;
            listView2.LargeImageList = imageList1;
        }

        private void get_pic_thumbnail() {
            string imageDir = @"// 画像ディレクトリパス//"; 
            string[] jpgFiles = System.IO.Directory.GetFiles(imageDir, "*.PNG");

            int width = 80;
            int height = 80;

            imageList1.ImageSize = new Size(width, height);
            listView1.LargeImageList = imageList1;

            // imageList , listView 登録
            for (int i = 0; i < jpgFiles.Length; i++)
            {
                String F_Name = Path.GetFileName(jpgFiles[i]);
                Image original = Bitmap.FromFile(jpgFiles[i]);
                Image thumbnail = createThumbnail(original, width, height);

                imageList1.Images.Add("KEY_"+F_Name, thumbnail);
                
                listView1.Items.Add(F_Name, "KEY_" + F_Name);
                listView2.Items.Add(F_Name, i);
                original.Dispose();
                thumbnail.Dispose();
            }

            // リストビュー1(listView1)プロパティ
            int listViewCnt1 = listView1.Items.Count;
            string[,] dat_vw1 = new string[listViewCnt1, 4];
            for (int i = 0; i < listViewCnt1; i++) {
                dat_vw1[i, 0] = listView1.Items[i].Index.ToString();
                dat_vw1[i, 1] = listView1.Items[i].Text;
                dat_vw1[i, 2] = listView1.Items[i].ImageIndex.ToString();
                dat_vw1[i, 3] = listView1.Items[i].ImageKey;

                listBox1.Items.Add(dat_vw1[i, 0]+"  ,  "+ dat_vw1[i, 1]+ "  ,  "+ dat_vw1[i, 2] + "  ,  " + dat_vw1[i, 3]);
            }

            // リストビュー2(listView2)プロパティ
            int listViewCnt2 = listView2.Items.Count;
            string[,] dat_vw2 = new string[listViewCnt2, 4];
            for (int i = 0; i < listViewCnt2; i++)
            {
                dat_vw2[i, 0] = listView2.Items[i].Index.ToString();
                dat_vw2[i, 1] = listView2.Items[i].Text;
                dat_vw2[i, 2] = listView2.Items[i].ImageIndex.ToString();
                dat_vw2[i, 3] = listView2.Items[i].ImageKey;

                listBox2.Items.Add(dat_vw2[i, 0] + "  ,  " + dat_vw2[i, 1] + "  ,  " + dat_vw2[i, 2] + "  ,  " + dat_vw2[i, 3]);
            }

            // イメージリスト(imageList1)プロパティ
            int ImagelistCnt = imageList1.Images.Count;
            string[,] dat_img = new string[ImagelistCnt, 2];
            for (int i = 0; i < ImagelistCnt; i++)
            {
                dat_img[i, 0] = imageList1.Images.Keys[i];
                dat_img[i, 1] = imageList1.Images.IndexOfKey(dat_img[i, 0]).ToString();
                listBox3.Items.Add(i.ToString() + "  ,  " + dat_img[i, 0]+"  ,  " + dat_img[i, 1]) ;
            }
        }

        // 幅w、高さhのImageオブジェクトを作成
        Image createThumbnail(Image image, int w, int h)
        {
            Bitmap canvas = new Bitmap(w, h);
            Graphics g = Graphics.FromImage(canvas);
            g.FillRectangle(new SolidBrush(Color.White), 0, 0, w, h);

            float fw = (float)w / (float)image.Width;
            float fh = (float)h / (float)image.Height;

            float scale = Math.Min(fw, fh);
            fw = image.Width * scale;
            fh = image.Height * scale;

            g.DrawImage(image, (w - fw) / 2, (h - fh) / 2, fw, fh);
            g.Dispose();

            return canvas;
        }
    }
}

 

簡単な画像表示順の変更

 簡単に順番の並び替えをしてみました。下図では上段に対し、下段の画像は反対から並んでいます。

 上記の並び替え順番の変更は、今回のテストプログラムの53行目を次の様に変更しました。

 listView2.Items.Add(F_Name, i);

 F_Name = Path.GetFileName(jpgFiles[jpgFiles.Length – 1 – i]);
listView2.Items.Add(F_Name, jpgFiles.Length-1-i);


 次回は、今回確認した listViewの使い方をもう少し発展させていく予定です。