IT정보공유/C#

[ C# ] 리스트뷰(ListView) 컬럼 헤더 클릭시 숫자 컬럼까지도 완벽하게 정렬하는 방법

알지오™ 2016. 12. 21.

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 클래스를 좀 가공하면 임의의 정렬 방식을 만들어 낼 수도 있겠죠?

잘 활용해 보시기 바랍니다.


♡ 여러분의 공감이 빅에너지에게 에너지원입니다. 공감, 좋아요 부탁합니다~ 

댓글

💲 추천 글