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