Thứ năm, ngày 23 tháng 10 năm 2014

C# – Ví dụ về VirtualMode trong ListView: Nạp danh sách tập tin trong thư mục

Ngày đăng: 12/3/2012, 13:49:48PM | Lượt xem: 2,252
Hot!

VirtualMode là một phương pháp để bạn tự quản lý dữ liệu trong ListView (hoặc DataGridView) với mục đích chính là tăng tốc độ hiển thị trong những trường hợp phải nạp quá nhiều dữ liệu lên ListView. Với phương pháp này, dữ liệu sẽ không được thêm trực tiếp vào ListView mà chúng sẽ được tạo động khi cần thiết để hiển thị. Trong bài viết này tôi sẽ làm một ví dụ để nạp và tìm kiếm tập tin trong một thư mục trên ListView.

VirtualMode là một phương pháp để bạn tự quản lý dữ liệu trong ListView (hoặc DataGridView) với mục đích chính là tăng tốc độ hiển thị trong những trường hợp phải nạp quá nhiều dữ liệu lên ListView. Với phương pháp này, dữ liệu sẽ không được thêm trực tiếp vào ListView mà chúng sẽ được tạo động khi cần thiết để hiển thị. Trong bài viết này tôi sẽ làm một ví dụ để nạp và tìm kiếm tập tin trong một thư mục trên ListView.

Download ListView VirtualMode Example (VC# 2010)

Giới thiệu

Để sử dụng được phương pháp này, đầu tiên bạn cần đặt property VirtualMode bằng true. Sau đó bạn cần gán property VirtualListSize bằng số phần tử mà ListView chứa.

Một vài điểm cần lưu ý là các property của ListView như Items, CheckedItems, SelectedItems sẽ không được sử dụng nữa. Thay vào đó, bạn hãy sử dụng CheckedIndices và SelectedIndices để thay thế.

Ngoài ra khi để chế độ View là Tile, nó sẽ được tự động chuyển sang chế độ LargeIcon.

Trong ví dụ này tôi tạo một lớp Y2ListView thừa kế từ ListView để thực hiện các công việc cần thiết. Lớp này có property FolderPath, mỗi khi gán giá trị mới cho property này, ListView sẽ được cập nhật lại để lấy và hiển thị danh sách tập tin trong thư mục đó.

Sự kiện RetrieveVirtualItem

Trong chế độ VirtualMode, sự kiện RetrieveVirtualItem sẽ được gọi khi ListView cần lấy một phần tử nào đó. Bạn cần khởi tạo phần tử và gán cho property Item của tham số RetrieveVirtualItemEventArgs. Dựa vào property ItemIndex của tham số này, bạn có thể lấy được giá trị cần thiết từ dữ liệu nguồn để tạo ra phần tử.

    public class Y2ListView:ListView
    {
        string[] _files;
        // data
        private string _folderPath;
        public string FolderPath
        {
            get {return _folderPath;}
            set
            {
                if(String.IsNullOrEmpty(value))
                    return;
                _folderPath=value;
                _files=Directory.GetFiles(_folderPath);
                Array.Sort(_files);

                this.VirtualListSize=_files.Length;
            }
        }

        public Y2ListView()
        {
            this.VirtualMode=true;
        }
        protected override void OnRetrieveVirtualItem(RetrieveVirtualItemEventArgs e)
        {
            string filePath=_files[e.ItemIndex];
            string fileName=Path.GetFileName(filePath);
            FileInfo finfo=new FileInfo(filePath);

            ListViewItem item=new ListViewItem(fileName,e.ItemIndex-_startIndex);

            double size=Math.Ceiling(finfo.Length/1024f);
            item.SubItems.Add(size.ToString("#,0 KB"));
            item.SubItems.Add(finfo.LastWriteTime.ToString());

            e.Item=item;

            base.OnRetrieveVirtualItem(e);
        }

    }
}

Bởi vì ListView mà tôi tạo ra sẽ có ba cột Name, Size, DateModified nên trong sự kiện RetrieveVirtualItem, bạn cũng cần phải tạo item có đủ ba giá trị (sub item).

Sự kiện CacheVirtualItems

Bạn có thể xử lý sự kiện này để tăng tốc độ cho ListView trong chế độ VirtualMode. Bằng cách tạo ra và lưu trữ sẵn các dữ liệu cần thiết sắp được sử dụng, việc truy xuất và hiển thị các phần tử sẽ nhanh hơn.

Ví dụ tôi thêm một ImageList để hiển thị icon cho các tập tin. Thay vì viết trực tiếp trong sự kiện RetrieveVirtualItem, tôi sẽ lưu trữ sẵn các icon cần thiết vào ImageList trong sự kiện CacheVirtualItems:

protected override void OnCacheVirtualItems(CacheVirtualItemsEventArgs e)
{
    _imageList.Images.Clear();
    for (int i = e.StartIndex; i < e.EndIndex; i++)
    {
        Icon icon=Icon.ExtractAssociatedIcon(_files[i]);
        _imageList.Images.Add(icon);
    }
    base.OnCacheVirtualItems(e);
}

Dựa vào property StartIndex và EndIndex, tôi chỉ lấy icon của các tập tin trong khoảng này và lưu vào ImageList. Như vậy ImageList sẽ có EndIndex-StartIndex phần tử tính từ 0,  như vậy ta cần một biến để lưu giá trị StartIndex lại nếu muốn gán ảnh cho ListViewItem thông qua ImageIndex.

Sự kiện SearchForVirtualItem

Sự kiện này cần được xử lý nếu bạn muốn sử dụng được hai phương thức FindItemWithText và FindNearestItem của ListView. Tham số SearchForVirtualItemEventArgs chứa property Text là giá trị của chuỗi tìm kiếm (trong ví dụ này là tên tập tin bao gồm phần mở rộng), và Index là giá trị mà bạn cần gán cho nó để xác định phần tử nào tìm được trong danh sách. Bởi vì danh sách file của ta đã được sắp xếp, tôi sử dụng BinarySearch để hiện thực sự kiện này đơn giản như sau:

protected override void OnSearchForVirtualItem(SearchForVirtualItemEventArgs e)
{
    string filePath=Path.Combine(_folderPath,e.Text);
    int index=Array.BinarySearch(_files,filePath);

    if(index>-1)
        e.Index=index;
    base.OnSearchForVirtualItem(e);
}

Mã nguồn hoàn chỉnh lớp Y2ListView

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;

namespace Win1
{
    public class Y2ListView:ListView
    {
        private ImageList _imageList;
        int _startIndex;

        string[] _files;

        private string _folderPath;
        public string FolderPath
        {
            get {return _folderPath;}
            set
            {
                if(String.IsNullOrEmpty(value))
                    return;
                if(_imageList!=null)
                    _imageList.Images.Clear();

                _startIndex=-1;
                _folderPath=value;
                _files=Directory.GetFiles(_folderPath);
                Array.Sort(_files);

                this.VirtualListSize=_files.Length;
            }
        }

        public Y2ListView()
        {
            _imageList=new ImageList();
            _imageList.ImageSize = new System.Drawing.Size(16, 16);

            this.VirtualMode=true;
            this.DoubleBuffered=true;
            this.SmallImageList=_imageList;
            this.LargeImageList=_imageList;

        }
        protected override void OnSearchForVirtualItem(SearchForVirtualItemEventArgs e)
        {
            string filePath=Path.Combine(_folderPath,e.Text);
            int index=Array.BinarySearch(_files,filePath);
            if(index>-1)
                e.Index=index;
            base.OnSearchForVirtualItem(e);
        }
        protected override void OnCacheVirtualItems(CacheVirtualItemsEventArgs e)
        {
            if(_startIndex==e.StartIndex)
                return;
            _startIndex=e.StartIndex;
            _imageList.Images.Clear();
            for (int i = e.StartIndex; i < e.EndIndex; i++)
            {
                Icon icon=Icon.ExtractAssociatedIcon(_files[i]);
                _imageList.Images.Add(icon);
            }
            base.OnCacheVirtualItems(e);
        }

        protected override void OnRetrieveVirtualItem(RetrieveVirtualItemEventArgs e)
        {
            string filePath=_files[e.ItemIndex];
            string fileName=Path.GetFileName(filePath);
            FileInfo finfo=new FileInfo(filePath);

            ListViewItem item=new ListViewItem(fileName,e.ItemIndex-_startIndex);

            double size=Math.Ceiling(finfo.Length/1024f);
            item.SubItems.Add(size.ToString("#,0 KB"));
            item.SubItems.Add(finfo.LastWriteTime.ToString());

            e.Item=item;

            base.OnRetrieveVirtualItem(e);
        }
    }
}

http://yinyangit.wordpress.com

 Chia sẻ qua: 
Hot!
Ý kiến bạn đọc

These items will be permanently deleted and cannot be recovered. Are you sure?

Gallery

image

Maecenas viverra rutrum pulvinar

Maecenas viverra rutrum pulvinar! Aenean vehicula nulla sit amet metus aliquam et malesuada risus aliquet. Vestibulum rhoncus, dolor sit amet venenatis porta, metus purus sagittis nisl, sodales volutpat elit lorem…

Read more

Text Links

Thiết kế logo chuyên nghiệp Insky
DAFABET
W88 w88b.com/dang-ky-tai-khoan-w88
W88
Copyright © 2011 - 2012 vietshare.vn by phamkhuong102@gmail.com doanhkisi2315@gmail.com. All rights reserved.