可排序列表视图控件






4.19/5 (9投票s)
.NET Compact Framework 中的 ListView 控件得到了 SortListView 控件的扩展,使其能够对项目进行排序,并在列标题中显示排序状态。
引言
我决定通过使用 .NET Compact Framework 编写一个 C# 项目,一举两得,既能掌握 .Net,又能掌握 Pocket PC 开发。
为此项目,我需要一个可排序的列表视图控件;我想,这不成问题——我将使用 .Net Framework 中的控件。这时,你会发现文档中的许多方法和属性都没有“由 .NET Compact Framework 支持”这两个魔法字眼,包括 ListView.Sort 方法。因此,我决定自己编写一个,名为 SortListView。市面上可能还有其他类似的类,但我将其视为一次学习练习。
事实证明,这是一个不错的选择,因为它还需要与非托管代码进行一些互操作,这也是我希望进一步学习的内容。
如何使用 SortListView
类
我已尽力使 SortListView
类的使用尽可能简单。
- 在窗体设计器中,将一个
ListView
控件拖放到窗体上,并根据需要调整其位置和大小。此步骤仅用于设置ListView
控件的 Size 和 Location 属性。如果愿意,也可以手动将其输入到代码中。 - 在 Form 类构造函数中,为
ListView
中的每个所需列创建一个AdrianStanley.Windows.Forms.SortListView
控件和一个AdrianStanley.Windows.Forms.SortColumnHeader
控件,并将它们添加到 ListView 对象的 Columns 集合中。 - 确保
ListView
控件的View
属性设置为System.Windows.Forms.View.Details
。 - 为每个
SortColumnHeader
对象设置其ColumnHeaderSorter
属性。这决定了如何对列中的项目进行排序。该属性应设置为派生自AdrianStanley.Windows.Forms.SortComparer
的类的实例。我提供了几个这样的类(参见 SortComparer.cs),用于对字符串、整数、双精度浮点数和日期进行排序。 - 像往常一样,以
ListViewItem
对象的格式向ListView
控件添加项目。 - 为目标平台生成非托管 dll,ControlEx.dll,并将该 dll 添加到主 .Net 项目中。下载中包含此 dll 的 Pocket PC 2003 的构建版本。
就这些了。最初,ListView
中的项目是未排序的。当您第一次单击列标题时,该列中的项目将按升序排序,并且在列标题文本旁边会显示一个向上箭头。当您再次单击列标题时,箭头会变为向下,并且列将按降序排序。
示例项目
为了演示这有多么简单,这里有一个完整的 C# Windows 项目,它创建了一个具有三个列的排序 ListView。
using System;
using System.Globalization;
using System.Windows.Forms;
using AdrianStanley.Windows.Forms;
namespace SortListViewDemo
{
public class SortListViewForm : System.Windows.Forms.Form
{
// Declare SortListView and three SortColumnHeader objects.
private AdrianStanley.Windows.Forms.SortListView m_sortListView;
private AdrianStanley.Windows.Forms.SortColumnHeader m_colhdrName;
private AdrianStanley.Windows.Forms.SortColumnHeader m_colhdrAmount;
private AdrianStanley.Windows.Forms.SortColumnHeader m_colhdrDate;
public SortListViewForm()
{
// Create SortListView and three SortColumnHeader objects.
m_sortListView = new AdrianStanley.Windows.Forms.SortListView();
m_colhdrName = new AdrianStanley.Windows.Forms.SortColumnHeader();
m_colhdrDate = new AdrianStanley.Windows.Forms.SortColumnHeader();
m_colhdrAmount=new AdrianStanley.Windows.Forms.SortColumnHeader();
m_sortListView.Columns.Add(m_colhdrName);
m_sortListView.Columns.Add(m_colhdrDate);
m_sortListView.Columns.Add(m_colhdrAmount);
m_sortListView.Size = new System.Drawing.Size(248, 272);
m_sortListView.View = System.Windows.Forms.View.Details;
m_colhdrName.Text = "Name";
m_colhdrName.Width = 100;
m_colhdrDate.Text = "Date";
m_colhdrDate.Width = 80;
m_colhdrAmount.Text = "Amount";
m_colhdrAmount.Width = 60;
m_colhdrAmount.TextAlign = HorizontalAlignment.Right;
Controls.Add(m_sortListView);
Text = "SortListView Demo";
// Assign specific comparers to each column header.
m_colhdrName.ColumnHeaderSorter = new ComparerString();
m_colhdrDate.ColumnHeaderSorter = new ComparerStringAsDateTime();
m_colhdrAmount.ColumnHeaderSorter = new ComparerStringAsDouble();
// Add items to ListView control.
m_sortListView.BeginUpdate();
AddItem("Green, David", new DateTime(2001, 12, 31), 100.23);
AddItem("Brown, Tom", new DateTime(2000, 4, 3), 56.98);
AddItem("Pink, Jane", new DateTime(1996, 6, 15), 653.18);
AddItem("White, Sarah", new DateTime(2006, 8, 23), 345.22);
AddItem("Grey, Richard", new DateTime(2003, 9, 18), 27.74);
m_sortListView.EndUpdate();
}
private void AddItem(string name, DateTime date, double amount)
{
string[] displayInfo = new string[3];
displayInfo[0] = name;
displayInfo[1] = date.ToString("d");
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalDigits = 2;
displayInfo[2] = amount.ToString("N", nfi);
m_sortListView.Items.Add(new ListViewItem(displayInfo));
}
protected override void Dispose( bool disposing )
{
m_sortListView.Dispose();
base.Dispose( disposing );
}
static void Main()
{
Application.Run(new SortListViewForm());
}
}
}
持久化状态
如果需要,SortListView
类可以持久化状态。持久化的状态包括当前排序列的索引以及每列的排序顺序。持久化机制使用了 OpenNETCF.Win32
命名空间,该命名空间可从 http://www.opennetcf.org/ 获取。持久化机制默认是禁用的,因为并非每个人都会拥有 OpenNETCF.Win32
命名空间。要启用持久化机制,请在项目设置中定义预处理器常量 PERSIST_SORTLISTVIEW
,将 SortListView.PersistKeyName
属性设置为用于在注册表中持久化值的键,然后调用 LoadState
和 SaveState
方法分别从注册表中加载状态并将其保存到注册表中。
我建议为 SortListView.PersistKeyName
属性使用“SOFTWARE\CompanyName\ProductName\ListViewName”形式的值。
主类
该项目涉及三个主要类。我使用了 .Net 开发环境的 XML 注释功能来记录这些类,因此有关详细信息,我建议您阅读这些注释——最好是在生成 HTML 文件后(工具,生成注释网页...)。
SortListView
SortListView
类表示一个 Windows 列表视图控件,它显示详细视图中一组已排序的项目。SortListView
类扩展了现有的 .Net Compact Framework ListView 类,当它在详细视图中使用时,ListView.View
设置为 View.Details
。在详细视图中,ListView
控件有一个列标题。当单击列标题时,SortListView
类会自动对 ListView 控件中的项目进行排序。
首次单击列标题时,该列中的项目将按升序排序。该列现在是已排序的列;其他列中项目的顺序遵循所单击列中项目的顺序。再次单击列标题将按降序对项目进行排序。列标题中会显示一个排序箭头,以显示排序方向——向上箭头表示升序,向下箭头表示降序。默认情况下,排序箭头显示在列标题文本的右侧。如果列标题文本右对齐,则排序箭头将显示在文本的左侧。
每列都有自己的排序顺序,以及用于确定如何对列中的项目进行排序的比较器。排序顺序定义为 enum AdrianStanley.Windows.Forms.SortOrder
的值之一,比较器定义为派生自 AdrianStanley.Windows.Forms.SortComparer
的类的实例。AdrianStanley.Windows.Forms
命名空间定义了一些现有的比较器,用于对 string
、int
、short
、long
、double
和 DateTime
对象进行排序。
SortListView
类需要非托管代码(包含在 ControlEx.dll 中)才能在列标题中显示排序箭头。
SortColumnHeader
SortColumnHeader
类显示 SortListView
控件中的单个列,并代表 AdrianStanley.Windows.Forms.SortListView
控件中的列标题。
列标题是 SortListView
控件中的一个项,包含标题文本和排序顺序。可以使用基类 ListView.ColumnHeaderCollection
类的 Add
方法将 SortColumnHeader
对象添加到 SortListView
中。
SortColumnHeader
提供 Sorting
属性来设置该列的排序顺序,以及 SortComparer
属性来设置用于对该列中的项目进行排序的比较器。
SortComparer
SortComparer
类与 SortListView.Sort
方法结合使用,并提供了一种自定义 SortListView
中项目排序顺序的方法。
该类标记为抽象类,因为它充当派生类(实现 Compare
方法)的基类。
提供了几个派生自 SortComparer
的类
ComparerString
。比较字母字符串。CompareStringAsShort
。比较表示为字符串的 short 类型。CompareStringAsInt
。比较表示为字符串的 int 类型。CompareStringAsLong
。比较表示为字符串的 long 类型。CompareStringAsDouble
。比较表示为字符串的 double 类型。CompareStringAsDateTime
。比较表示为字符串的日期。