HOW TO:排序 ListView 項目
更新:2007 年 11 月
.NET Compact Framework 不支援 ListView 的 Sort 方法,但是您仍然可以使用 IComparer 介面來排序項目,並在 ArrayList 上使用 Sort 方法。
下表定義三個類別。
類別 |
說明 |
---|---|
ColHeader |
這個類別衍生自 ColumnHeader 類別,用於將資料行加入至 ListView 控制項,以及排序所點選的資料行。它包括指定排序方向的 ascending 屬性:true 指定遞增,false 則指定遞減。 |
SortWrapper |
點選資料行時,會對每個 ListItem 建立此類別的執行個體,然後將它加入至 ArrayList。每個包裝的項目都包括一個屬性,內含已點選資料行的索引。 這個類別包含 SortComparer 類別。 |
SortComparer |
在 SortWrapper 類別內,這個類別會定義 IComparer 介面的實作,排序 ArrayList 時,該介面的 Compare 方法會一次比較兩個物件。 |
ColumnClick 事件的事件處理常式會執行排序作業,如下所示:
建立 ColHeader 類別的執行個體,以判斷點選了哪個資料行。
設定 ColHeader 物件的 ascending 屬性,以反方向排序。
取得清單中的項目數目。
在使用 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(); }
編譯程式碼
這個範例需要下列命名空間的參考:
請參閱
概念
.NET Compact Framework HOW TO 主題