使用vb.net 對 Windows Form 按列排序 ListView 項目

來源:互聯網
上載者:User
window|排序|項目 使用 Windows Form 按列排序 ListView 項目

摘要: 說明如何根據所單擊的列在 Microsoft .NET 中的 ListView 控制項提供項目排序。

簡介

ListView 控制項是顯示檔案系統資訊和顯示 XML 或資料庫資料的非常好的方式。ListView 控制項通常用於顯示表示項目以及項目文本的圖形表徵圖。此外,ListView 控制項還可以用於顯示有關子項目中項目的其他資訊。例如,如果 ListView 控制項顯示一列檔案,您可以配置 ListView 控制項來顯示作為子項目的諸如檔案大小和屬性的詳細資料。要顯示 ListView 控制項中的子項目資訊,必須將 View 屬性設定為 View.Details。此外,您必須建立 ColumnHeader 對象並將這些對象分配給 ListView 控制項的 Columns 屬性。在設定這些屬性後,項目以行和列格式進行顯示,類似於 DataGrid 控制項。以這種方式顯示項目的能力使 ListView 控制項為從任意類型的資料來源顯示資料提供了快速、簡便的解決方案。

對 ListView 控制項進行排序是通過使用 ListView 的 Sorting 屬性而提供的。這使您可以定義要應用到項目的排序類型。如果您只想按項目排序,這是一個非常好的功能。如果您要按子項目排序,必須使用 ListView 控制項的自訂排序功能。本文將說明如何在 ListView 控制項中執行自訂排序,以及在排序時如何處理特殊的資料類型條件。



ListView 控制項的自訂排序功能

ListView 控制項提供了您可以使用排序的功能,而不是由 Sorting 屬性提供。當 ListView 控制項使用 Sorting 屬性排序項目時,它使用一個實現 System.Collections.IComparer 介面的類。這個類提供用於排序每個項目的排序功能。為了按子項目進行排序,您必須建立自己的類,來實現反過來可以實現 ListView 控制項所需排序的 IComparer 介面。該類利用建構函式進行定義,該建構函式可以指定 ListView 控制項排序所用的列。在您建立這個類後(通常將其作為表單的嵌套類),您可以建立該類的一個執行個體,並將其分配到 ListView 的 ListViewItemSorter 屬性。當調用 Sort 方法時,這會確定 ListView 控制項將要使用的自訂排序類。Sort 方法執行 ListView 項目的實際排序。

升序排序

以下部分提供的基本樣本說明了在 ListView 控制項中基於其子項目的排序。該樣本說明了以升序排序 ListView 控制項中的項目。升序排序或降序排序將會在本文的稍後部分進行說明。此處的目標就是說明在 ListView 控制項中進行自訂排序的基本要求。

初始化控制項

如果要開始,請建立 ListView 控制項的執行個體,並將其添加到表單中。在控制項位於表單上後,使用 Items 屬性將項目添加到 ListView 控制項。您可以添加任意多的項目,只要確保每個項目的文本都是唯一的。在您建立項目時,為每個項目添加兩個子項目。第一個子項目應該包含數字資訊,第二個子項目包含日期資訊。下面的表格樣本說明該資訊在 ListView 控制項中可能如何顯示。

項目
子項目 1
子項目 2

Alpha
1.0
4/5/1945

Charlie
3.5
1/9/1920

Bravo
2.4
12/8/1930


建立兩個 ColumnHeader 對象,並將它們分配到 ListView 控制項的 Columns 屬性中。將 View 屬性設定為 View.Details。

處理 ColumnClick 事件

為了確定按哪個子項目集進行排序,您需要瞭解使用者何時單擊某個子項目的欄位標題。為此,您需要為 ListView 的 ColumnClick 事件建立一個事件處理方法。將事件處理方法作為表單中的一個成員,並確保它包含的簽名相似於下面程式碼範例所顯示的簽名。

'Visual Basic

Private Sub listView1_ColumnClick(sender As Object, e As System.Windows.Forms.ColumnClickEventArgs)

End Sub

//C#

private void listView1_ColumnClick(object sender, System.Windows.Forms.ColumnClickEventArgs e)

{

}

通過向表單的建構函式中添加代碼,將事件處理方法串連到 ListView 控制項,如下面的樣本所示。

'Visual Basic

AddHandler listView1.ColumnClick, AddressOf Me.listView1_ColumnClick

//C#

this.listView1.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.listView1_ColumnClick);

將下面的代碼添加到用於 ColumnClick 事件的事件處理方法。

'Visual Basic

' Set the ListViewItemSorter property to a new ListViewItemComparer

' object.

Me.listView1.ListViewItemSorter = New ListViewItemComparer(e.Column)

' Call the sort method to manually sort.

listView1.Sort()

//C#

// Set the ListViewItemSorter property to a new ListViewItemComparer

// object.

this.listView1.ListViewItemSorter = new ListViewItemComparer(e.Column);

// Call the sort method to manually sort.

listView1.Sort();

添加到事件處理方法的代碼會利用 ListViewItemComparer 類(在下一部分中定義)的新執行個體來設定 ListView 控制項的 ListViewItemSorter 屬性,然後分配要單擊的列。被單擊的列作為事件參數的組成部分進行傳遞。在設定 ListViewItemSorter 屬性後,調用 Sort 方法來執行手動排序。

建立 ListViewItemComparer 類

正如前面提到的那樣,在 ListView 控制項中進行自訂排序的關鍵在於建立實現 System.Collections.IComparer 介面的類。就是這個類為項目提供排序。對於這個樣本,定義了名為 ListViewItemComparer 的類,並且將其添加為表單的嵌套類。ListViewItemComparer 執行傳遞到其建構函式的指定列的基本升序排序。將以下類定義添加到 Form 類並確保它在表單內是正確嵌套的。

'Visual Basic

' Implements the manual sorting of items by column.

Class ListViewItemComparer

Implements IComparer

Private col As Integer



Public Sub New()

col = 0

End Sub



Public Sub New(column As Integer)

col = column

End Sub



Public Function Compare(x As Object, y As Object) As Integer _

Implements System.Collections.IComparer.Compare

Dim returnVal as Integer = -1

returnVal = [String].Compare(CType(x, _

ListViewItem).SubItems(col).Text, _

CType(y, ListViewItem).SubItems(col).Text)

Return returnVal

End Function

End Class

//C#

// Implements the manual sorting of items by column.

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;

}

}

以一個名為 Compare 的 IComparer 介面的必要方法執行排序。這個方法將兩個對象作為參數,而參數會包含要進行比較的兩個項目。當在 ListView 控制項的 ColumnClick 事件處理方法中調用 Sort 方法時,Sort 方法會使用已定義並已指派到 ListViewItemSorter 屬性的 ListViewItemComparer 對象,並且調用其 Compare 方法。建立 ListViewItemComparer 對象後,分配給它被單擊的列的索引。該列的索引用於從需要進行排序的列中訪問子項目。然後,將子項目傳遞到 String.Compare 方法,該方法比較項目並返回三個結果中的一個。如果 x 參數中的項目小於 y 參數中的項目,則返回一個小於零的值。如果兩個項目相同,則返回零。最後,如果 x 參數中的值大於 y 參數中的值,則返回一個大於零的值。Compare 方法返回的值傳遞迴 Sort 方法,這確定正在比較的每個項目在列中的位置。Sort 方法可以根據在所選擇列中排序所有子項目的需要對 Compare 方法調用任意多次。

前面的樣本就完成了。如果您運行該樣本並單擊 ListView 控制項的欄位標題,項目將會按字母順序或數字順序進行適當地排序。唯一不能正確排序的列就是包含日期資訊的列。稍後本文將介紹排序日期列。

這個樣本說明了在 ListView 控制項中執行基本手動項目排序所需要的基本要素。接下來的部分會擴充這個樣本,提供升序和降序排序功能。

升序或降序排序

ListView 控制項的使用者將期望具有同時以升序和降序排序項目的功能。為了實現這個功能,需要對前面的樣本進行某些改動,以便使 Compare 方法可以確定要排序的項目。

對表單的更改

通常情況下,要在升序和降序排序之間切換,您要多次單擊欄位標題。使用者期望如果他們單擊欄位標題,排序將會發生,隨後再次單擊將更改排序次序。前面的程式碼範例需要能夠確定何時多次單擊列。為此,您可以將一個私人整數變數添加到 Form 類。這個變數儲存上一次單擊的列。ColumnClick 事件處理方法將使用這個變數來比較上一次的列與當前單擊的列,並確定它們是否相同。將以下成員定義添加到 Form 類中。

'Visual Basic

Dim sortColumn as Integer = -1

//C#

private int sortColumn = -1;

ColumnClick 事件處理方法的更改

在前面的樣本中定義的 ColumnClick 事件處理方法需要進行修改,以便跟蹤單擊過的列和當前排序次序。添加以下代碼以替換在前面的樣本中建立的 ColumnClick 事件處理方法中的代碼。

'Visual Basic

Private Sub listView1_ColumnClick(sender As Object, e As

System.Windows.Forms.ColumnClickEventArgs)

' Determine whether the column is the same as the last column clicked.

If e.Column <> sortColumn Then

' Set the sort column to the new column.

sortColumn = e.Column

' Set the sort order to ascending by default.

listView1.Sorting = SortOrder.Ascending

Else

' Determine what the last sort order was and change it.

If listView1.Sorting = SortOrder.Ascending Then

listView1.Sorting = SortOrder.Descending

Else

listView1.Sorting = SortOrder.Ascending

End If

End If

' Call the sort method to manually sort.

listView1.Sort()

' Set the ListViewItemSorter property to a new ListViewItemComparer

' object.

listView1.ListViewItemSorter = New ListViewItemComparer(e.Column, _

listView1.Sorting)

End Sub

//C#

private void listView1_ColumnClick(object sender,

System.Windows.Forms.ColumnClickEventArgs e)

{

// Determine whether the column is the same as the last column clicked.

if (e.Column != sortColumn)

{

// Set the sort column to the new column.

sortColumn = e.Column;

// Set the sort order to ascending by default.

listView1.Sorting = SortOrder.Ascending;

}

else

{

// Determine what the last sort order was and change it.

if (listView1.Sorting == SortOrder.Ascending)

listView1.Sorting = SortOrder.Descending;

else

listView1.Sorting = SortOrder.Ascending;

}

// Call the sort method to manually sort.

listView1.Sort();

// Set the ListViewItemSorter property to a new ListViewItemComparer

// object.

this.listView1.ListViewItemSorter = new ListViewItemComparer(e.Column,

listView1.Sorting);

}

該代碼在設定 ListViewItemSorter 屬性和調用 Sort 方法之前添加了一些邏輯。增加的代碼確定當前單擊的項目與上一次已經單擊過的列是否相同。如果不同,就會設定 sortColumn 變數,並且將 SortOrder.Ascending 值分配給 Sorting 屬性。如果 sortColumn 變數和當前單擊的列相同,則 Sorting 屬性將更改為相反的排序次序。在這個樣本中,Sorting 屬性用作定義項目排序次序的方法。因為您在使用自訂的比較程式類來排序項目,所以設定 Sorting 屬性對排序操作沒有任何影響。在該樣本中,它只是簡單地用作一個變數。

在指定排序次序後,對 ColumnClick 事件處理方法代碼的唯一其他更改就是將附加參數值添加到 ListViewItemComparer 對象的建立中,而該對象是您要分配到 ListViewItemSorter 屬性的對象。正如這個樣本的後面部分所示,ListViewItemComparer 類包含一個指定排序次序的新參數。您使用 ListView.Sorting 屬性的值,將值分配給該參數。

ListViewItemComparer 類的更改

使該樣本可以以升序或降序進行排序的上面的一系列更改就是對 ListViewItemComparer 類的更改。增加的代碼將執行以兩種排序模式之一比較項目所需的邏輯。添加以下代碼以替換在前面的樣本中為 ListViewItemComparer 定義的代碼。

'Visual Basic

' Implements the manual sorting of items by columns.

Class ListViewItemComparer

Implements IComparer

Private col As Integer

Private order as SortOrder



Public Sub New()

col = 0

order = SortOrder.Ascending

End Sub



Public Sub New(column As Integer, order as SortOrder)

col = column

Me.order = order

End Sub



Public Function Compare(x As Object, y As Object) As Integer _

Implements System.Collections.IComparer.Compare

Dim returnVal as Integer = -1

returnVal = [String].Compare(CType(x, _

ListViewItem).SubItems(col).Text, _

CType(y, ListViewItem).SubItems(col).Text)

' Determine whether the sort order is descending.

If order = SortOrder.Descending Then

' Invert the value returned by String.Compare.

returnVal *= -1

End If

Return returnVal

End Function

End Class

//C#

// Implements the manual sorting of items by columns.

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);

// Determine whether the sort order is descending.

if(order == SortOrder.Descending)

// Invert the value returned by String.Compare.

returnVal *= -1

return returnVal;

}

}33

該代碼將排序次序參數添加到建構函式,並且建立一個用於儲存該值的私人變數。Compare 方法的代碼已更改,以便確定排序次序是否為降序。如果是,則將String.Compare 方法的傳回值乘以 -1 以更改該值,這樣 Compare 方法返回的值就與 String.Compare 返回的值相反。

運行該代碼並單擊列。該列以升序順序進行排列。單擊相同的列,列就會以降序進行排序。同樣,日期列沒有正確的排序,因為它被儲存為一個字串而不是日期。在接下來的部分中,通過添加功能來按日期或者按字串進行排序(這取決於資料的類型),從而完成該樣本。

排序日期

作為項目而置於 ListView 控制項中的資料顯示為文本並以文本的形式進行儲存。這使得使用 IComparer 類中的 String.Compare 方法進行排序變得非常簡單。String.Compare 可以對字母字元和數字進行排序。但是,使用 String.Compare 不能對特定資料類型進行正確排序,例如日期和時間資訊。因此,System.DateTime 結構具有一個與 String 類相同作用的 Compare 方法。這個方法可以用來基於時間順序執行相同類型的排序。在本部分中,您只需修改 Compare 方法就可以正確排序日期。

添加以下代碼以替換為 Compare 方法(該方法是前面樣本中定義的 ListViewItemComparer 類的方法)而定義的代碼。

'Visual Basic

Public Function Compare(ByVal x As Object, ByVal y As Object) As

Integer Implements System.Collections.IComparer.Compare

Dim returnVal As Integer

' Determine whether the type being compared is a date type.

Try

' Parse the two objects passed as a parameter as a DateTime.

Dim firstDate As System.DateTime = DateTime.Parse(CType(x, _

ListViewItem).SubItems(col).Text)

Dim secondDate As System.DateTime = DateTime.Parse(CType(y, _

ListViewItem).SubItems(col).Text)

' Compare the two dates.

returnVal = DateTime.Compare(firstDate, secondDate)

' If neither compared object has a valid date format,

' compare as a string.

Catch

' Compare the two items as a string.

returnVal = [String].Compare(CType(x, _

ListViewItem).SubItems(col).Text, CType(y,ListViewItem).SubItems(col).Text)

End Try



' Determine whether the sort order is descending.

If order = SortOrder.Descending Then

' Invert the value returned by String.Compare.

returnVal *= -1

End If

Return returnVal

End Function

//C#

public int Compare(object x, object y)

{

int returnVal;

// Determine whether the type being compared is a date type.

try

{

// Parse the two objects passed as a parameter as a DateTime.

System.DateTime firstDate =

DateTime.Parse(((ListViewItem)x).SubItems[col].Text);

System.DateTime secondDate =

DateTime.Parse(((ListViewItem)y).SubItems[col].Text);

// Compare the two dates.

returnVal = DateTime.Compare(firstDate, secondDate);

}

// If neither compared object has a valid date format, compare

// as a string.

catch

{

// Compare the two items as a string.

returnVal = String.Compare(((ListViewItem)x).SubItems[col].Text,

((ListViewItem)y).SubItems[col].Text);

}

// Determine whether the sort order is descending.

if (order == SortOrder.Descending)

// Invert the value returned by 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 顯示和排序其內容的能力。




相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.