정리가 필요한 카테고리(추후 정리)/C#,Unity

C#] 리스트뷰(ListView) 컬럼 클릭하여 정렬하기

TwinParadox 2017. 12. 17. 16:04
728x90

리스트뷰 요소를 잘 보면 상단에 버튼처럼 클릭이 활성화된 항목들이 존재한다. 간혹 뭔가를 만들다 보면, 이들 항목을 기준으로, 즉 해당 칼럼을 기준으로 아이템들을 정렬해야 하는 경우가 생긴다.


이때 해당 리스트뷰(ListView)의 속성의 이벤트 탭에서 ColumnClick이라는 이벤트를 처리할 메서드를 지정하고 그 메서드에서 클릭된 칼럼을 분류, 그에 따른 정렬을 구현해주면 된다.


아래 그림은 DirectoryCleaner라는 말 그대로 디렉토리를 정리해주는 윈폼 프로그램으로 필자가 개인적으로 만들고 있는 프로그램 중 하나다.






특정 디렉토리에 저장된 파일들, 하위 디렉토리의 파일들까지 모두 탐색한 결과를 리스트뷰에 담아서 보여주고 있다. 이름, 경로, 최종 수정일, 용량에 대한 정보를 리스트 뷰에 저장했는데, 각 항목을 기준으로 정렬하는 기능을 한 번 구현해보도록 하자.








최초 클릭 시점에는 오름차순 정렬을, 두번째 클릭 시점을 기준으로는 내림차순 정렬을 실시하고 클릭 될 때마다 오름차순과 내림차순을 번갈아 가며 정렬을 수행하는데, 각 항목을 오름차순, 내림차순으로 결정 짓는 방법은 크게 두 가지 방법을 사용했다.



1. 파일 이름, 경로, 최종 수정일은 문자열의 사전 순서를 따른다.

사전 순서인 경우를 오름차순, 사전의 반대 순서인 경우를 내림차순으로 정의.


2. 용량은 숫자의 대소 비교를 따른다.

용량은 위 두 가지와는 상황이 조금 다르다. 크기라는 게 존재하기 때문에 문자열 정보를 숫자로 바꾸고 그 후 대소비교를 실시해 우리가 흔히 아는 오름차순, 내림차순을 적용한다.



private void lvFileList_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            this.lvFileList.ListViewItemSorter = new ListViewItemComparer(e.Column);
            if (sortStatus[e.Column] == 1)
                sortStatus[e.Column] = 2;
            else
                sortStatus[e.Column] = 1;
        }

        class ListViewItemComparer : IComparer
        {
            private int col;
            public ListViewItemComparer()
            {
                col = 0;
            }
            public ListViewItemComparer(int column)
            {
                col = column;
            }
            public int Compare(object x, object y)
            {
                if (col == 0 || col == 1 || col == 2)
                {
                    if (sortStatus[col] == 1)
                        return String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text);
                    else
                        return -String.Compare(((ListViewItem)x).SubItems[col].Text, ((ListViewItem)y).SubItems[col].Text);
                }
                else
                {
                    double dx, dy;
                    dx = Double.Parse(((ListViewItem)x).SubItems[col].Text);
                    dy = Double.Parse(((ListViewItem)y).SubItems[col].Text);
                    if (sortStatus[col] == 1)
                    {
                        if (dx < dy)
                            return -1;
                        else if (dx == dy)
                            return 0;
                        else
                            return 1;
                    }
                    else
                    {
                        if (dx < dy)
                            return 1;
                        else if (dx == dy)
                            return 0;
                        else
                            return -1;
                    }
                }
            }
        }



리스트뷰의 아이템을 정렬하는 것은 ListView.ListViewItemSorter이며 이를 통해서 리스트뷰를 제어한다. 정렬에 관련된 세부 내용은 ListViewItemComparer라는 클래스에서 이루어진다.


이 때 유의해야 할 부분은 반드시 인터페이스인 IComparer를 구현해야 한다. 여기서 다룰 정렬 방식은 기본적인 정렬로, 칼럼 값을 적절히 처리하는 생성자, 그리고 두 오브젝트(아이템)을 비교할 Compare 메서드만 구현하면 문제 없이 정렬을 수행할 수 있다.


필자는 여기서 오름차순, 내림차순 정렬을 선정하기 위한 변수와 조건문 하나를 더 넣었을 뿐, ColumnClick 이벤트를 통한 리스트뷰 아이템의 정렬에 대한 내용은 MSDN 문서(링크)와 다른 부분이 없다.


728x90