방법: ListView 항목 정렬
업데이트: 2007년 11월
.NET Compact Framework에서는 ListView에 대한 Sort 메서드를 지원하지 않지만 IComparer 인터페이스를 사용하여 항목을 정렬할 수 있으며 ArrayList에 있는 Sort 메서드를 사용할 수 있습니다.
다음 표에서는 세 개의 클래스를 정의합니다.
클래스 |
설명 |
---|---|
ColHeader |
이 클래스는 ColumnHeader 클래스에서 파생된 것으로 ListView 컨트롤에 열을 추가하고 클릭된 열을 정렬하는 데 사용됩니다. 이 클래스에는 정렬 방향을 지정하는 ascending 속성이 포함되어 있습니다. true이면 오름차순을 지정하고 false이면 내림차순을 지정합니다. |
SortWrapper |
열을 클릭하면 각 ListItem에 대해 이 클래스의 인스턴스가 만들어지고 ArrayList에 추가됩니다. 래핑된 각 항목에는 클릭된 열의 인덱스가 들어 있는 속성이 포함되어 있습니다. 이 클래스에는 SortComparer 클래스가 포함되어 있습니다. |
SortComparer |
SortWrapper 클래스 내에서 이 클래스는 ArrayList가 정렬될 때 한 번에 두 개씩 개체를 비교하는 Compare 메서드를 가지는 IComparer 인터페이스의 구현을 정의합니다. |
ColumnClick 이벤트의 이벤트 처리기는 다음과 같이 정렬 작업을 수행합니다.
클릭된 열을 확인하기 위해 ColHeader 클래스의 인스턴스를 만듭니다.
ColHeader 개체의 오름차순 속성을 설정하여 반대 방향으로 정렬합니다.
목록의 항목 수를 가져옵니다.
정렬하는 동안 BeginUpdate 메서드를 사용하여 표시가 그려지지 않도록 합니다.
Compare 메서드에 정렬 논리를 포함하는 IComparer 인터페이스가 구현된 SortComparer 클래스의 새 인스턴스를 사용하여 ArrayList의 요소를 정렬합니다.
EndUpdate 메서드를 사용하여 표시가 그려지도록 합니다.
ArrayList의 Sort 메서드는 불안정한 정렬을 수행합니다. 즉, 두 개의 요소가 같으면 해당 순서가 유지되지 않을 수도 있습니다. 이와 반대로 안정적인 정렬에서는 같은 요소의 순서가 유지됩니다.
응용 프로그램을 만들려면
SortComparer 클래스를 포함하는 프로젝트에 SortWrapper 클래스를 추가합니다.
' 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(); }
코드 컴파일
이 예제에는 다음과 같은 네임스페이스에 대한 참조가 필요합니다.