[C#] DataGridView 속도 개선하기
카테고리: C# + Unity
문제 상황
처음에는 DataTable.NewRow
를 수행하고 DataTable.Rows.Add
를 수행하는데 시간이 많이 소요되는 줄 알았다. 하지만, 디버깅 결과 DataGridView에 7개 Column과 80만 Row를 가진 DataTable을 바인딩하는 과정에서 굉장히 오랜 시간(5분 이상)이 소요되었다.
문제 확인
문제점을 확인하는데는 그리 오래걸리지 않았다. DataGridView에 설정한 DataGridViewAutoSizeColumnsMode
속성의 AllCells
때문이었다. 이를 None
으로 바꾸니 해결되었다.
이후 소스 코드를 수정하여 모두 불러온 후에 AllCells
를 지정하여 한번에 수행하도록 변경하였지만 오래걸리는 것은 매한가지 였다. 많은 블로그에서 소개한대로 더블 버퍼링도 해보고 VirtualMode
도 해봤지만, 드라마틱한 속도의 향상은 없었다.
결국 다시 None
으로 되돌려 속도를 얻게 되었지만, 수동으로 Column의 너비를 지정해줘야하는 문제점이 생겼다.
문제 해결
의외로 해당 셀에 들어오는 문자열의 길이를 파악하여 폰트 크기에 따른 너비를 유동적으로 계산하는 방법은 어렵지 않았다. TextRenderer.MeasureText
를 사용하면 금방이었기 때문이다.
private void AdjustDataGridViewColumnWidths(DataGridView dgv, int padding = 10) {
// 폰트는 DataGridView에서 사용하는 폰트를 기준으로 측정
Font font = dgv.Font;
// 각 컬럼에 대해 최적 너비를 계산
foreach (DataGridViewColumn col in dgv.Columns) {
int maxWidth = 0;
// 컬럼 헤더 텍스트도 고려 (헤더가 더 길 수 있으므로)
if (!string.IsNullOrEmpty(col.HeaderText)) {
int headerWidth = TextRenderer.MeasureText(col.HeaderText, font).Width;
if (headerWidth > maxWidth) {
maxWidth = headerWidth;
}
}
// 모든 행을 돌면서 셀의 텍스트 측정
foreach (DataGridViewRow row in dgv.Rows) {
// 보통은 빈 행(새로운 행) 등 체크
if (row.IsNewRow) {
continue;
}
string cellValue = row.Cells[col.Index].Value?.ToString() ?? string.Empty;
int cellWidth = TextRenderer.MeasureText(cellValue, font).Width;
if (cellWidth > maxWidth) {
maxWidth = cellWidth;
}
}
// 패딩을 더해 최종 컬럼 폭을 설정
col.Width = maxWidth + padding;
}
}
추가 처리
TextRenderer.MeasureText
를 사용할 때 결과 값이 5
가 나오는 경우가 있다. 이는 첫번째 매개변수에 들어가는 텍스트의 길이가 너무 길어서 내부적으로 ...
으로 표시되었기 때문이다. 이를 휴리스틱하게 short.MaxValue
등으로 설정하면 된다.
참고
https://learn.microsoft.com/ko-kr/dotnet/api/system.windows.forms.datagridviewautosizecolumnsmode?view=windowsdesktop-9.0
https://stackoverflow.com/questions/10226992/slow-performance-in-populating-datagridview-with-large-data