C#의 리스트뷰를 컬럼별로 정렬하는 기능이 필요할 때 참고할 만한 소스를 제공해 드렸었는데요.
기본적으로 리스트 뷰의 소트 방식이 텍스트 정렬이기 때문에
숫자 컬럼에서 정확한 정렬기능이 동작 안하다고 설명을 했습니다.
2016/12/20 - [IT/프로그래밍] - [ C# ] 리스트뷰(ListView) 컬럼 클릭 정렬 하는 방법
그래서 숫자 컬럼 까지도 완벽하게 정렬을 하기 위해서는 약간의 C# 고급진 기능을 사용해야 합니다.
OOP 개념이나 인터페이스에 약한 초보 분들에게는 조금 이해하기 어려울 수도 있습니다.
ListView 컨트롤의 ColumnClick 이벤트 핸들러는 정의 한다는 건 기본적으로 동일합니다.
private void listView_ColumnClick(object sender, ColumnClickEventArgs e) { if (listView.Sorting == SortOrder.Ascending) { listView.Sorting = SortOrder.Descending; } else { listView.Sorting = SortOrder.Ascending; } listView.ListViewItemSorter = new Sorter(); // * 1 Sorter s = (Sorter)listView.ListViewItemSorter; s.Order = listView.Sorting; s.Column = e.Column; listView.Sort(); }
주석 처리된 * 1 부분이 중요합니다.
이게 무슨 의미인지 해석을 해보겠습니다.
리스트뷰의 기본 비교 인터페이스인 IComparer ListViewItemSorter 에 새로운 비교 인터페이스를 지정해주는 겁니다.
Sorter 라는 인터페이스는 C#에 없는 인터페이스고, 새로 만들어낸 인터페이스입니다.
인터페이스 원형을 한번 살펴 보시죠.
class Sorter : System.Collections.IComparer { public int Column = 0; public System.Windows.Forms.SortOrder Order = SortOrder.Ascending; public int Compare(object x, object y) // IComparer Member { if (!(x is ListViewItem)) return (0); if (!(y is ListViewItem)) return (0); ListViewItem l1 = (ListViewItem)x; ListViewItem l2 = (ListViewItem)y; if (l1.ListView.Columns[Column].Tag == null) // 리스트뷰 Tag 속성이 Null 이면 기본적으로 Text 정렬을 사용하겠다는 의미 { l1.ListView.Columns[Column].Tag = "Text"; } if (l1.ListView.Columns[Column].Tag.ToString() == "Numeric") // 리스트뷰 Tag 속성이 Numeric 이면 숫자 정렬을 사용하겠다는 의미 { string str1 = l1.SubItems[Column].Text; string str2 = l2.SubItems[Column].Text; if (str1 == "") { str1 = "99999"; } if (str2 == "") { str2 = "99999"; } float fl1 = float.Parse(str1); //숫자형식으로 변환해서 비교해야 숫자정렬이 되겠죠? float fl2 = float.Parse(str2); //숫자형식으로 변환해서 비교해야 숫자정렬이 되겠죠? if (Order == SortOrder.Ascending) { return fl1.CompareTo(fl2); } else { return fl2.CompareTo(fl1); } } else { // 이하는 텍스트 정렬 방식 string str1 = l1.SubItems[Column].Text; string str2 = l2.SubItems[Column].Text; if (Order == SortOrder.Ascending) { return str1.CompareTo(str2); } else { return str2.CompareTo(str1); } } } }
대략적으로 핵심만 정리하자면, IComparer 를 통해서 리스트뷰에 있는 각 로우를 비교하고 비교하고 비교해야
정렬을 할 수 있는데, 기본적으로 리스트뷰는 문자열 정렬이기 때문에 숫자 컬럼에서 정렬이 정상적으로 되지 않는다.
.
그래서 위의 ICompare 인터페이스를 상속받는 Sorter 클래스를 직접 구현해서
문자열 비교 컬럼과 숫자 컬럼 비교 방식을 바꿔줘야 한다. 이런 뜻입니다.
말주변이 없어서 이해가 잘 되시려나 모르겠네요.
이해가 안되실땐 소스 복사하기 붙여넣기 하셔서 사용하시면 잘 될겁니다.
다만 숫자 정렬이 필요한 리스트뷰의 컬럼에는 아래 사진과 같이 Tag 속에서 Numeric 이라고 직접 입력을 해놓아야 합니다.
Sorter 클래스를 좀 가공하면 임의의 정렬 방식을 만들어 낼 수도 있겠죠?
잘 활용해 보시기 바랍니다.
♡ 여러분의 공감이 빅에너지에게 에너지원입니다. 공감, 좋아요 부탁합니다~ ♡
댓글