如何:对 ListView 项排序
更新:2007 年 11 月
.NET Compact Framework 不支持 ListView 的 Sort 方法,但您仍可以通过 IComparer 接口对项进行排序,并使用 ArrayList 的 Sort 方法。
下表定义了三个类。
类 |
说明 |
---|---|
ColHeader |
此类派生自 ColumnHeader 类,用于向 ListView 控件添加列并对已单击的列进行排序。它包含指定排序方向的 ascending 属性:true 表示升序,false 表示降序。 |
SortWrapper |
单击某列时,将为每个 ListItem 创建此类的一个实例,并将这些实例添加到 ArrayList。每个包装项均包含一个属性,其中含有已单击列的索引。 此类包含 SortComparer 类。 |
SortComparer |
在 SortWrapper 类中,此类用于定义 IComparer 接口的实现,该接口的 Compare 方法可以在对 ArrayList 进行排序时比较对象(每次两个)。 |
ColumnClick 事件的事件处理程序按照下面的过程执行排序操作:
创建 ColHeader 类的一个实例,以确定已单击的列。
设置 ColHeader 对象的升序属性以按相反方向排序。
获取列表中的项数。
使用 BeginUpdate 方法在排序过程中禁止绘制显示内容。
使用 SortComparer 类的新实例对 ArrayList 中的元素进行排序,该类的 IComparer 接口的实现在其 Compare 方法中包含排序逻辑。
使用 EndUpdate 方法允许绘制显示内容。
注意,ArrayList 中的 Sort 方法执行的是不稳定的排序,也就是说,如果两个元素相等,它们的顺序可能不会保持不变。相反,稳定排序则会保持相等元素的顺序。
创建应用程序
将 SortWrapper 类添加到项目中,该项目还包含了 SortComparer 类。
' An instance of the SortWrapper class is created for ' each item and added to the ArrayList for sorting. Public Class SortWrapper Friend sortItem As ListViewItem Friend sortColumn As Integer ' A SortWrapper requires the item and the index of the clicked column. Public Sub New(ByVal Item As ListViewItem, ByVal iColumn As Integer) sortItem = Item sortColumn = iColumn End Sub ' Text property for getting the text of an item. Public ReadOnly Property [Text]() As String Get Return sortItem.SubItems(sortColumn).Text End Get End Property ' Implementation of the IComparer ' interface for sorting ArrayList items. Public Class SortComparer Implements IComparer Private ascending As Boolean ' Constructor requires the sort order; ' true if ascending, otherwise descending. Public Sub New(ByVal asc As Boolean) Me.ascending = asc End Sub ' Implemnentation of the IComparer:Compare ' method for comparing two objects. Public Function [Compare](ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare Dim xItem As SortWrapper = CType(x, SortWrapper) Dim yItem As SortWrapper = CType(y, SortWrapper) Dim xText As String = xItem.sortItem.SubItems(xItem.sortColumn).Text Dim yText As String = yItem.sortItem.SubItems(yItem.sortColumn).Text Return xText.CompareTo(yText) * IIf(Me.ascending, 1, -1) End Function End Class End Class
// An instance of the SortWrapper class is created for // each item and added to the ArrayList for sorting. public class SortWrapper { internal ListViewItem sortItem; internal int sortColumn; // A SortWrapper requires the item and the index of the clicked column. public SortWrapper (ListViewItem Item, int iColumn) { sortItem = Item; sortColumn = iColumn; } // Text property for getting the text of an item. public string Text { get { return sortItem.SubItems[sortColumn].Text; } } // Implementation of the IComparer // interface for sorting ArrayList items. public class SortComparer : IComparer { bool ascending; // Constructor requires the sort order; // true if ascending, otherwise descending. public SortComparer(bool asc) { this.ascending = asc; } // Implemnentation of the IComparer:Compare // method for comparing two objects. public int Compare(object x, object y) { SortWrapper xItem = (SortWrapper) x; SortWrapper yItem = (SortWrapper) y; string xText = xItem.sortItem.SubItems[xItem.sortColumn].Text; string yText = yItem.sortItem.SubItems[yItem.sortColumn].Text; return xText.CompareTo(yText) * (this.ascending ? 1 : -1); } } }
将 ColHeader 类添加到项目中。
' The ColHeader class is a ColumnHeader object with an ' added property for determining an ascending or descending sort. ' True specifies an ascending order, false specifies a descending order. Public Class ColHeader Inherits ColumnHeader Public ascending As Boolean Public Sub New(ByVal [text] As String, ByVal width As Integer, ByVal align As HorizontalAlignment, ByVal asc As Boolean) Me.Text = [text] Me.Width = width Me.TextAlign = align Me.ascending = asc End Sub End Class
// The ColHeader class is a ColumnHeader object with an // added property for determining an ascending or descending sort. // True specifies an ascending order, false specifies a descending order. public class ColHeader : ColumnHeader { public bool ascending; public ColHeader(string text, int width, HorizontalAlignment align, bool asc) { this.Text = text; this.Width = width; this.TextAlign = align; this.ascending = asc; } }
使用 ColHeader 类添加列,然后添加 ListView 项。
' Set to Details view. Me.listView1.View = View.Details ' Add columns using the ColHeader class. The fourth ' parameter specifies true for an ascending sort order. listView1.Columns.Add(New ColHeader("Name", 110, HorizontalAlignment.Left, True)) listView1.Columns.Add(New ColHeader("Region", 50, HorizontalAlignment.Left, True)) listView1.Columns.Add(New ColHeader("Sales", 70, HorizontalAlignment.Left, True)) ' Add the data. listView1.Items.Add(New ListViewItem(New String() {"Archer, Karen", "4", "0521.28"})) listView1.Items.Add(New ListViewItem(New String() {"Benson, Max", "8", "0828.54"})) listView1.Items.Add(New ListViewItem(New String() {"Bezio, Marin", "3", "0535.22"})) listView1.Items.Add(New ListViewItem(New String() {"Higa, Sidney", "2", "0987.50"})) listView1.Items.Add(New ListViewItem(New String() {"Martin, Linda", "6", "1122.12"})) listView1.Items.Add(New ListViewItem(New String() {"Nash, Mike", "7", "1030.11"})) listView1.Items.Add(New ListViewItem(New String() {"Sanchez, Ken", "1", "0958.78"})) listView1.Items.Add(New ListViewItem(New String() {"Smith, Ben", "5", "0763.25"})) ' Connect the ListView.ColumnClick event to the ColumnClick event handler. AddHandler Me.listView1.ColumnClick, AddressOf listView1_ColumnClick
this.listView1.View = View.Details; // Add columns using the ColHeader class. The fourth // parameter specifies true for an ascending sort order. listView1.Columns.Add(new ColHeader("Name", 110, HorizontalAlignment.Left, true)); listView1.Columns.Add(new ColHeader("Region", 50, HorizontalAlignment.Left, true)); listView1.Columns.Add(new ColHeader("Sales", 70, HorizontalAlignment.Left, true)); // Add the data. listView1.Items.Add(new ListViewItem(new string[] {"Archer, Karen","4","0521.28"})); listView1.Items.Add(new ListViewItem(new string[] {"Benson, Max","8","0828.54"})); listView1.Items.Add(new ListViewItem(new string[] {"Bezio, Marin","3","0535.22"})); listView1.Items.Add(new ListViewItem(new string[] {"Higa, Sidney","2","0987.50"})); listView1.Items.Add(new ListViewItem(new string[] {"Martin, Linda","6","1122.12"})); listView1.Items.Add(new ListViewItem(new string[] {"Nash, Mike","7","1030.11"})); listView1.Items.Add(new ListViewItem(new string[] {"Sanchez, Ken","1","0958.78"})); listView1.Items.Add(new ListViewItem(new string[] {"Smith, Ben","5","0763.25"})); // Connect the ListView.ColumnClick event to the ColumnClick event handler. this.listView1.ColumnClick += new ColumnClickEventHandler(listView1_ColumnClick);
添加代码以执行排序。
Private Sub listView1_ColumnClick(ByVal sender As Object, ByVal e As ColumnClickEventArgs) ' Create an instance of the ColHeader class. Dim clickedCol As ColHeader = CType(Me.listView1.Columns(e.Column), ColHeader) ' Set the ascending property to sort in the opposite order. clickedCol.ascending = Not clickedCol.ascending ' Get the number of items in the list. Dim numItems As Integer = Me.listView1.Items.Count ' Turn off display while data is repoplulated. Me.listView1.BeginUpdate() ' Populate an ArrayList with a SortWrapper of each list item. Dim SortArray As New ArrayList Dim i As Integer For i = 0 To numItems - 1 SortArray.Add(New SortWrapper(Me.listView1.Items(i), e.Column)) Next i ' Sort the elements in the ArrayList using a new instance of the SortComparer ' class. The parameters are the starting index, the length of the range to sort, ' and the IComparer implementation to use for comparing elements. Note that ' the IComparer implementation (SortComparer) requires the sort ' direction for its constructor; true if ascending, othwise false. SortArray.Sort(0, SortArray.Count, New SortWrapper.SortComparer(clickedCol.ascending)) ' Clear the list, and repopulate with the sorted items. Me.listView1.Items.Clear() Dim z As Integer For z = 0 To numItems - 1 Me.listView1.Items.Add(CType(SortArray(z), SortWrapper).sortItem) Next z ' Turn display back on. Me.listView1.EndUpdate() End Sub
private void listView1_ColumnClick(object sender, ColumnClickEventArgs e) { // Create an instance of the ColHeader class. ColHeader clickedCol = (ColHeader)this.listView1.Columns[e.Column]; // Set the ascending property to sort in the opposite order. clickedCol.ascending = !clickedCol.ascending; // Get the number of items in the list. int numItems = this.listView1.Items.Count; // Turn off display while data is repoplulated. this.listView1.BeginUpdate(); // Populate an ArrayList with a SortWrapper of each list item. ArrayList SortArray = new ArrayList(); for (int i = 0; i < numItems; i++) { SortArray.Add(new SortWrapper(this.listView1.Items[i], e.Column)); } // Sort the elements in the ArrayList using a new instance of the SortComparer // class. The parameters are the starting index, the length of the range to sort, // and the IComparer implementation to use for comparing elements. Note that // the IComparer implementation (SortComparer) requires the sort // direction for its constructor; true if ascending, othwise false. SortArray.Sort(0, SortArray.Count, new SortWrapper.SortComparer(clickedCol.ascending)); // Clear the list, and repopulate with the sorted items. this.listView1.Items.Clear(); for (int i = 0; i < numItems; i++) this.listView1.Items.Add(((SortWrapper)SortArray[i]).sortItem); // Turn display back on. this.listView1.EndUpdate(); }
编译代码
此示例需要引用下面的命名空间: