본문 바로가기
개발언어/C#

[C#]ListView – Columns 컬럼 동적 크기 조정

by 창용이랑 2021. 10. 12.
728x90

DataGridView는 각 열의 너비를 정의할 때 많은 옵션을 제공한다. 개인적으로 가장 좋아하는 것은 AutoSizeMode 속성을 Fill로 설정한 다음 각 열에 대해 FillWeight를 정의하는 것이다. 이렇게 하면 사용자가 양식 크기를 어떻게 조정하든 FillWeight 속성에 따라 각 열의 크기가 자동으로 조정된다. ListView 컨트롤을 상세 모드로 사용할 때 그런 속성을 찾고 있었는데 그런 기능이 없는 것 같아.

 

여기 MSDN 설명서에 따르면, 열 머리글 너비 속성을 -1로 설정하면 열 너비가 열에서 가장 긴 항목으로 자동 조정되고 열 머리글 너비 속성을 -2로 설정하면 열 머리글 너비가 자동으로 열 머리글 크기에 맞게 조정된다. 그러나 DataGridView에서와 같이 각 열의 비례성을 자동으로 조정하는 Fill 설정은 없다.

 

여기서 가장 간단한 해결책은 DataGridView를 사용하고 ListView를 완전히 삭제하는 것이지만, 내 상황에서 ListView는 DataGridView를 사용할 수 있다는 것에 훨씬 더 만족스럽게 데이터를 렌더링했다. 그런 해결책이 없다는 것을 감안하여, 나는 ListView를 이용하여 직접 작성하기로 했다.크기변경된 이벤트. ListView.Size변경된 이벤트는 ListView 크기가 변경될 때마다 발생하므로, 이 이벤트에서 약간의 논리로 DataGridView에서 수행한 것처럼 열의 자동 싸이징을 프로그래밍 방식으로 에뮬레이트할 수 있다.

 

고지 사항: 이를 구현하는 가장 좋은 방법은 다음과 같은 논리를 포함하는 ListView 클래스에서 파생된 사용자 정의 컨트롤을 만드는 것이다. 단순성을 위해 Stock ListView 컨트롤과 SizeChanged 이벤트를 방금 사용했었습니다.

 

ListView 열을 정의할 때 설계 시간에 태그 속성에 정수로 열의 원하는 FillWeight를 입력하십시오. 원래는 Width 속성만 사용하려고 했지만 계산된 폭이 0이 되었을 때 정확한 값을 복구하는 데 문제가 생겼다. 태그 속성에 FillWeight를 설정하면 제어 수명(실시간 내에 변경되지 않도록 보장할 수 있는 경우) 동안 FillWeight가 일정하게 유지됨 다시 말하지만, 사용자 정의 컨트롤을 생성한 경우 태그 속성을 사용하는 대신 사용자 정의 FillWeight 속성을 생성하십시오.

 

쉽게말해) 밑에 그림의 Tag의 1은 비율(퍼센트라고 생각하면 된다)이다. 소스는 태그값을 참고하여 비율계산하는것이다.

 

아래 ex처럼 비율로 입력하면 비율대로 늘어나고 줄어든다.

ex)

columnHeader1 = 20    (20%)

columnHeader1 = 30    (30%)

columnHeader1 = 50    (50%)

그런 다음 SizeChanged 이벤트에 이어지는 코드를 넣으십시오. 이 코드는 각 열이 점유해야 하는 공간의 비율을 계산한 다음 ListView 컨트롤이 점유하는 가시 공간에 따라 열의 폭을 적절하게 설정한다. ListView의 크기를 조정할 때 이 코드를 여러 번 호출한다. 수행된 계산 횟수를 줄이기 위해 크기 조정 플래그를 사용하십시오.

 

private bool Resizing = false;
 
private void ListView_SizeChanged(object sender, EventArgs e)
{
    // Don't allow overlapping of SizeChanged calls
    if (!Resizing)
    {
        // Set the resizing flag
        Resizing = true;
 
        ListView listView = sender as ListView;
        if (listView != null)
        {                               
            float totalColumnWidth = 0;
 
            // Get the sum of all column tags
            for (int i = 0; i < listView.Columns.Count; i++)
                totalColumnWidth += Convert.ToInt32(listView.Columns[i].Tag);
 
            // Calculate the percentage of space each column should 
            // occupy in reference to the other columns and then set the 
            // width of the column to that percentage of the visible space.
            for (int i = 0; i < listView.Columns.Count; i++)
            {
                float colPercentage = (Convert.ToInt32(listView.Columns[i].Tag) / totalColumnWidth);
                listView.Columns[i].Width = (int)(colPercentage * listView.ClientRectangle.Width);             
            }
        }
    }
 
    // Clear the resizing flag
    Resizing = false;
}

아래 예에서는 FillWeight가 각각 1, 2, 1인 세 개의 열이 있다. 따라서 제1열과 제3열은 ListView 가시 공간의 25%를 차지하고, 제2열은 50%를 점유해야 한다. 자동 크기 조정 결과는 다양한 폼 너비에 대해 아래에 나와 있다.

이 논리를 사용하려는 양식에 ListView 컨트롤이 여러 개 있는 경우, 각 SizeChanged 이벤트를 아래와 같은 코드로 연결하면 된다는 점에 유의하십시오. 이러한 이유로 나는 발신인 개체를 직접 참조만 하지 않고 ListView에 캐스팅했다.

public Form1()
{
    InitializeComponent();
    this.listView1.SizeChanged += new EventHandler(ListView_SizeChanged);
    this.listView2.SizeChanged += new EventHandler(ListView_SizeChanged);
    this.listView3.SizeChanged += new EventHandler(ListView_SizeChanged);    
}

 

출처 : https://nickstips.wordpress.com/2010/11/10/c-listview-dynamically-sizing-columns-to-fill-whole-control/