zoukankan      html  css  js  c++  java
  • 关于ListView排序的众多问题

     

    最近需要在软件中增加FTP功能,说是简单的功能,但是做起来也遇到了不少问题。主要问题就是目录浏览的问题,如何从FTP返回的列表中分割出大小、修改时间等也是当初没有想到的。而在列表展示上使用ListView控件的主要原因就是ListView控件"添加"数据比较自然,而DataGridView更多的是"绑定"数据。
    随后发现ListView没有排序功能。
    其实排序功能还是有的,只不过需要自己给定一个比较器。

    listView1.ListViewItemSorter = XXXComparer.Instance(XXXComparer : IComparer)

    这就是我FTP的窗口。只显示了文件名、大小和修改时间,文件名中目录使用[目录名]的方式展示,文件名的排序方式按道理上来讲应该是向上、目录、文件这种顺序。大小和修改时间就不用多说了。
    这时候,问题就出来了:ListView的项(SubItem)没有数据类型一说。
    对此,给我ListViewSubItem增加了一个强类型的ListViewSubItem:

    /// <summary>
    /// 强类型ListViewSubItem
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ListViewTypeSubItem<T> : ListViewItem.ListViewSubItem
    {
        public ListViewTypeSubItem()
        {
            ValueType = typeof(T);
        }
    
        public Type ValueType { get; set; }
    
        public T Value { get; set; }
    }

    当然,这个所谓的强类型还是有一定的问题。暂时这么着吧。
    有了强类型的 ListViewSubItem 那么给ListView赋值就要有相应的修改。

    foreach (var file in files)
    {
        lvi = new ListViewItem(file.IsDirectory ? string.Format("[{0}]", file.Name) : file.Name);
    
        size = new ListViewTypeSubItem<long>();
        size.Text = file.Size.ToString("N0");
        size.Value = file.Size;
        lvi.SubItems.Add(size);
    
        date = new ListViewTypeSubItem<DateTime>();
        date.Text = file.CreateTime.ToString("yyyy-MM-dd HH:mm");
        date.Value = file.CreateTime;
        lvi.SubItems.Add(date);
    
        lvi.Tag = file.IsDirectory ? FileTypeEnum.Directory : FileTypeEnum.File;
    
        lvFtpFile.Items.Add(lvi);
    }

    当然,重要的比较器还没有写。这里列出我写的比较器,其中应该有点问题,因为当初没有想让他能点两次。也就是说没有想让他支持点一次是asc,再点一次就是desc。本来只是想做个排序,让大小和修改时间逆序排,而文件名就按我上面说的规则排列。最后需求有所变动。
    说了半天,列出我的比较器:

    /// <summary>
    /// ListViewItem自定义排序
    /// 对long类型和DateTime类型进行处理(DESC)
    /// 对于字符串,目录排在文件上面,向上排在最上边
    /// </summary>
    public class ListViewItemComparer : IComparer
    {
        private static int col;
        private static bool isDesc = false;
    
        public ListViewItemComparer(int column)
        {
            col = column;
        }
    
        public int Compare(object x, object y)
        {
            int result = 0;
            var sub = ((ListViewItem)x).SubItems[col];
            if (sub is ListViewTypeSubItem<long>)
            {
                var sub_x = ((ListViewItem)x).SubItems[col] as ListViewTypeSubItem<long>;
                var sub_y = ((ListViewItem)y).SubItems[col] as ListViewTypeSubItem<long>;
                if (sub_x.Value > sub_y.Value)
                {
                    result = 1;
                }
                else if (sub_x.Value == sub_y.Value)
                {
                    result = 0;
                }
                else
                {
                    result = -1;
                }
            }
            else if (sub is ListViewTypeSubItem<DateTime>)
            {
                var sub_x = ((ListViewItem)x).SubItems[col] as ListViewTypeSubItem<DateTime>;
                var sub_y = ((ListViewItem)y).SubItems[col] as ListViewTypeSubItem<DateTime>;
    
                result = DateTime.Compare(sub_y.Value, sub_x.Value);
            }
            else
            {
                string sub_x = ((ListViewItem)x).SubItems[col].Text;
                string sub_y = ((ListViewItem)y).SubItems[col].Text;
                if ((sub_x[0] == '[' && sub_x[sub_x.Length - 1] == ']') &&
                (sub_y[0] != '[' || sub_y[sub_y.Length - 1] != ']'))
                {
                    return -1;
                }
                else
                {
                    result = string.Compare(sub_x, sub_y);
                }
            }
    
            var lvi_x = (ListViewItem)x;
            var lvi_y = (ListViewItem)y;
    
            if (lvi_x.Text == "[..]")
            {
                return -1;
            }
    
            //if (lvi_y.Text == "[..]")
            //{
            //   return isDesc ? 1 : -1;
            //}
    
            return isDesc ? result : result == 0 ? 0 : result == 1 ? -1 : 1;
        }
    
        public static ListViewItemComparer Sort(int column = 0)
        {
            isDesc = !isDesc;
    
            return new ListViewItemComparer(column);
        }
    }

    应该从代码中更能感觉到曾经改过的样子。
    自我感觉上面的

    return isDesc ? result : result == 0 ? 0 : result == 1 ? -1 : 1;

    一定会有人说。哈哈。

    我的博客原文地址:关于ListView排序的众多问题

    欢迎来我的博客:nanqi.info

  • 相关阅读:
    VC++菜单
    VC++的菜单控制和自绘菜单
    windowsUI的总结
    Linux mount BSD disk partition
    Linux qemu-nbd mount qemu disk image
    自定义chromium浏览器
    EF6配合MySQL或MSSQL(CodeFirst模式)配置指引
    使用 dmidecode 查看Linux服务器信息
    修改KVM的模拟网卡类型
    华为TaiShan 2280 ARM 服务器
  • 原文地址:https://www.cnblogs.com/nanqi/p/ListViewSort.html
Copyright © 2011-2022 走看看