您的位置:首页 > 其它

Windows Form 按列排序 ListView 项目

2011-11-08 13:41 232 查看

1、简介

  ListView 控件是显示文件系统信息和显示 XML 或数据库数据的非常好的方式。ListView 控件通常用于显示表示项目以及项目文本的图形图标。此外,ListView 控件还可以用于显示有关子项目中项目的其他信息。例如,如果 ListView 控件显示一列文件,您可以配置 ListView 控件来显示作为子项目的诸如文件大小和属性的详细信息。要显示 ListView 控件中的子项目信息,必须将 View 属性设置为 View.Details。此外,您必须创建 ColumnHeader 对象并将这些对象分配给 ListView 控件的 Columns 属性。在设置这些属性后,项目以行和列格式进行显示,类似于 DataGrid 控件。以这种方式显示项目的能力使 ListView 控件为从任意类型的数据源显示数据提供了快速、简便的解决方案。

  对 ListView 控件进行排序是通过使用 ListViewSorting 属性而提供的。这使您可以定义要应用到项目的排序类型。如果您只想按项目排序,这是一个非常好的功能。如果您要按子项目排序,必须使用 ListView 控件的自定义排序功能。本文将说明如何在 ListView 控件中执行自定义排序,以及在排序时如何处理特殊的数据类型条件。

2、ListView 控件的自定义排序功能

  ListView 控件提供了您可以使用排序的功能,而不是由 Sorting 属性提供。当 ListView 控件使用 Sorting 属性排序项目时,它使用一个实现 System.Collections.IComparer 接口的类。这个类提供用于排序每个项目的排序功能。为了按子项目进行排序,您必须创建自己的类,来实现反过来可以实现 ListView 控件所需排序的 IComparer 接口。该类利用构造函数进行定义,该构造函数可以指定 ListView 控件排序所用的列。在您创建这个类后(通常将其作为窗体的嵌套类),您可以创建该类的一个实例,并将其分配到 ListViewListViewItemSorter 属性。当调用 Sort 方法时,这会确定 ListView 控件将要使用的自定义排序类。Sort 方法执行 ListView 项目的实际排序。

3、创建 [b]ListView 控件的实例[/b]

  在控件位于窗体上后,使用 Items 属性将项目添加到 ListView 控件。您可以添加任意多的项目,只要确保每个项目的文本都是唯一的。在您创建项目时,为每个项目添加两个子项目。第一个子项目应该包含数字信息,第二个子项目包含日期信息。下面的表格示例说明该信息在 ListView 控件中可能如何显示。

  创建两个 ColumnHeader 对象,并将它们分配到 ListView 控件的 Columns 属性中。将 View 属性设置为 View.Details

4、处理 ColumnClick 事件

  为了确定按哪个子项目集进行排序,您需要了解用户何时单击某个子项目的列标题。为此,您需要为 ListViewColumnClick 事件创建一个事件处理方法。将事件处理方法作为窗体中的一个成员,并确保它包含的签名相似于下面代码示例所显示的签名。

View Code

// 设定一个新的ListViewItemComparer ListViewItemSorter 对象
this.listView1.ListViewItemSorter = new ListViewItemComparer(e.Column);
// 呼出手动排序类
listView1.Sort();


  添加到事件处理方法的代码会利用 ListViewItemComparer 类(在下一部分中定义)的新实例来设置 ListView 控件的 ListViewItemSorter 属性,然后分配要单击的列。被单击的列作为事件参数的组成部分进行传递。在设置 ListViewItemSorter 属性后,调用 Sort 方法来执行手动排序。

5、创建 ListViewItemComparer

  正如前面提到的那样,在 ListView 控件中进行自定义排序的关键在于创建实现 System.Collections.IComparer 接口的类。就是这个类为项目提供排序。对于这个示例,定义了名为 ListViewItemComparer 的类,并且将其添加为窗体的嵌套类。ListViewItemComparer 执行传递到其构造函数的指定列的基本升序排序。将以下类定义添加到 Form 类并确保它在窗体内是正确嵌套的。

// 实行手工对项目的列进行排序.
class ListViewItemComparer : IComparer {
private int col;
public ListViewItemComparer() {
col=0;
}
public ListViewItemComparer(int column)
{
col=column;
}
public int Compare(object x, object y)
{
int returnVal = -1;
returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text,
((ListViewItem)y).SubItems[col].Text);
return returnVal;
}
}


  以一个名为 CompareIComparer 接口的必要方法执行排序。这个方法将两个对象作为参数,而参数会包含要进行比较的两个项目。当在 ListView 控件的 ColumnClick 事件处理方法中调用 Sort 方法时,Sort 方法会使用已定义并已分配到 ListViewItemSorter 属性的 ListViewItemComparer 对象,并且调用其 Compare 方法。创建 ListViewItemComparer 对象后,分配给它被单击的列的索引。该列的索引用于从需要进行排序的列中访问子项目。然后,将子项目传递到 String.Compare 方法,该方法比较项目并返回三个结果中的一个。如果 x 参数中的项目小于 y 参数中的项目,则返回一个小于零的值。如果两个项目相同,则返回零。最后,如果 x 参数中的值大于 y 参数中的值,则返回一个大于零的值。Compare 方法返回的值传递回 Sort 方法,这确定正在比较的每个项目在列中的位置。Sort 方法可以根据在所选择列中排序所有子项目的需要对 Compare 方法调用任意多次。

  前面的示例就完成了。如果您运行该示例并单击 ListView 控件的列标题,项目将会按字母顺序或数字顺序进行适当地排序。唯一不能正确排序的列就是包含日期信息的列。

升序或降序排序

  ListView 控件的用户将期望具有同时以升序和降序排序项目的功能。为了实现这个功能,需要对前面的示例进行某些改动,以便使 Compare 方法可以确定要排序的项目。

1、对窗体的更改

  通常情况下,要在升序和降序排序之间切换,您要多次单击列标题。用户期望如果他们单击列标题,排序将会发生,随后再次单击将更改排序顺序。前面的代码示例需要能够确定何时多次单击列。为此,您可以将一个私有整数变量添加到 Form 类。这个变量存储上一次单击的列。ColumnClick 事件处理方法将使用这个变量来比较上一次的列与当前单击的列,并确定它们是否相同。将以下成员定义添加到 Form 类中。

  private int sortColumn = -1;

ColumnClick 事件处理方法的更改

  在前面的示例中定义的 ColumnClick 事件处理方法需要进行修改,以便跟踪单击过的列和当前排序顺序。添加以下代码以替换在前面的示例中创建的 ColumnClick 事件处理方法中的代码。

  

// 实现列的排序
class ListViewItemComparer : IComparer {
private int col;
private SortOrder order;
public ListViewItemComparer() {
col=0;
order = SortOrder.Ascending;
}
public ListViewItemComparer(int column, SortOrder order)
{
col=column;
this.order = order;
}
public int Compare(object x, object y)
{
int returnVal= -1;
returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text,
((ListViewItem)y).SubItems[col].Text);
// 确定排序顺序是否是降.
if(order == SortOrder.Descending)
//反转的String.Compare返回的值.
returnVal *= -1
return returnVal;
}

}


  该代码将排序顺序参数添加到构造函数,并且创建一个用于存储该值的私有变量。Compare 方法的代码已更改,以便确定排序顺序是否为降序。如果是,则将String.Compare 方法的返回值乘以 -1 以更改该值,这样 Compare 方法返回的值就与 String.Compare 返回的值相反。

  运行该代码并单击列。该列以升序顺序进行排列。单击相同的列,列就会以降序进行排序。同样,日期列没有正确的排序,因为它被存储为一个字符串而不是日期。在接下来的部分中,通过添加功能来按日期或者按字符串进行排序(这取决于数据的类型),从而完成该示例

2、排序日期

  作为项目而置于 ListView 控件中的数据显示为文本并以文本的形式进行存储。这使得使用 IComparer 类中的 String.Compare 方法进行排序变得非常简单。String.Compare 可以对字母字符和数字进行排序。但是,使用 String.Compare 不能对特定数据类型进行正确排序,例如日期和时间信息。因此,System.DateTime 结构具有一个与 String 类相同作用的 Compare 方法。这个方法可以用来基于时间顺序执行相同类型的排序。在本部分中,您只需修改 Compare 方法就可以正确排序日期。

  添加以下代码以替换为 Compare 方法(该方法是前面示例中定义的 ListViewItemComparer 类的方法)而定义的代码。

public int Compare(object x, object y)
{
int returnVal;
// 确定是否被比较的类型是日期类型.
try
{
// 解析两个对象作为参数传递作为一个DateTime.
System.DateTime firstDate =
DateTime.Parse(((ListViewItem)x).SubItems[col].Text);
System.DateTime secondDate =
DateTime.Parse(((ListViewItem)y).SubItems[col].Text);
// 比较两个日期.
returnVal = DateTime.Compare(firstDate, secondDate);
}
// 如果既没有比较的对象有一个有效的日期格式,作为一个字符串比较.
catch
{
// 作为一个字符串进行比较的两个项目.
returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text,
((ListViewItem)y).SubItems[col].Text);
}
// 确定排序顺序是否是降.
if (order == SortOrder.Descending)
// 反转的String.Compare返回的值.
returnVal *= -1;
return returnVal;
}


  通过将 x 和 y 参数存放到 DateTime 对象中,启动已添加用于替换 Compare 方法早期版本的代码。通过强制将两个正在比较的对象存放到 DateTime 对象中,在 try/catch 块中执行这个摘录以捕获可能出现的异常。如果出现异常,它发信号通知代码正在转换的类型是无效日期或时间,可以使用 String.Compare 方法进行排序。如果两个类型都是日期,它们使用 DateTime.Compare 方法进行排序。

运行该示例代码的这个新版本,并单击任意列。您将注意到它们正确地排序子项目,包括日期列。现在,该示例中的 ListView 控件可以正确地处理它所显示的所有数据类型。

小结

  ListView 控件能够提供以多种方式显示数据的能力。它可以用于显示单独项目,也可以显示包含子项目信息的项目。使用由 ListView 控件提供的排序功能,您还可以使用户基于那些子项目排序 ListView 控件中的项目,无需考虑出现的数据类型。这种对项目及其子项目进行排序的能力使您的应用程序能够以 Microsoft® Windows® Explorer 和其他应用程序的用户所熟悉的方式表现其行为,它们提供数据的 ListView 显示和排序其内容的能力。

原文地址:http://msdn.microsoft.com/zh-cn/library/ms996467.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: