! 제품 버전을 정확하게 입력해 주세요.
제품 버전이 정확하게 기재되어 있지 않은 경우,
최신 버전을 기준으로 안내 드리므로
더욱 빠르고 명확한 안내를 위해
제품 버전을 정확하게 입력해 주세요!

WinForms Datagrid를 빌드하고 최적화하는 방법 > 블로그 & Tips

본문 바로가기

ComponentOne

블로그 & Tips

WinForms Datagrid를 빌드하고 최적화하는 방법

페이지 정보

작성자 GrapeCity 작성일 2022-08-19 17:25 조회 2,097회 댓글 0건

본문

그리드 컨트롤의 도움으로 많은 양의 표 형식 데이터를 표시하는 경우 데이터를 렌더링, 스크롤, 필터링하거나 채울 때 그리드가 매우 느려지는 경험을 해보셨을 겁니다. 하지만 이러한 제한 사항을 극복할 수 있는 경우 사용자 환경을 개선하는 데 도움이 됩니다. 


이 블로그에서는 당시의 주력 컨트롤인 WinForms용 FlexGrid를 사용하여 가장 빠른 WinForms DataGrid를 최적화하고 만드는 잘 알려진 기술에 대해 알아봅니다.



데이터 가상화 사용


데이터 가상화는 더 짧은 기간에 많은 양의 데이터를 로드할 수 있도록 하여 데이터를 효율적으로 처리하게 합니다. WinForms용 FlexGrid는 향상된 성능으로 더 규모가 큰 데이터 집합의 데이터 가상화를 가능하게 하는 C1DataCollection을 사용하여 데이터 가상화를 지원합니다. 이 접근 방식에서는 그리드가 전체 행 수를 인식하지만 사용자가 목록에서 아래로 스크롤하는 행만 실시간으로 로드하여 표시합니다. 이 강력한 기능은 온디맨드 또는 증분 로드라고 합니다.


이를 구현하려면 C1VirtualDataCollection에서 상속하는 클래스를 만들고 설정한 데이터 원본에서 한 페이지의 데이터를 반환하는 GetPageAsync 메소드를 구현해야 합니다.


해당하는 코드는 다음과 같습니다.

public class VirtualModeCollectionView : C1VirtualDataCollection<Customer>
{
    public int TotalCount { get; set; } = 1000;
    protected override async Task<Tuple<int, IReadOnlyList<Customer>>> GetPageAsync(int pageIndex, int startingIndex, int count, IReadOnlyList<SortDescription> sortDescriptions = null, FilterExpression filterExpression = null, CancellationToken cancellationToken = default(CancellationToken))
{
  await Task.Delay(500, cancellationToken);//Simulates network traffic.
  return new Tuple<int, IReadOnlyList<Customer>>(TotalCount, Enumerable.Range(startingIndex, count).Select(i => new Customer(i)).ToList());
}
}


다음 GIF는 FlexGrid의 가상 스크롤 모드를 나타냅니다.

데이터 가상화

이 문서 페이지에는 데이터 가상화에 대한 더 많은 정보가 있습니다.



BeginUpdate 및 EndUpdate 메서드 사용


그리드의 성능은 BeginUpdateEndUpdate 메서드를 활용하여 개선할 수 있습니다. 중요한 변경을 하기 전에는 BeginUpdate 메서드를 호출하여 보기를 잠가 다시 표시 프로세스를 중지해야 합니다. 완료되고 나면 EndUpdate 메서드를 호출하여 보기를 잠금 해제하고 다시 칠하기 프로세스를 재개해야 합니다.


이 최적화는 범위를 다시 계산하고 스크롤 막대를 업데이트하므로 여러 행을 그리드에 추가할 때 유용합니다. 이로 인해 성능을 높이는 동안 깜박임이 줄어듭니다.


아래 코드를 사용하면 많은 행을 WinForms FlexGrid에 빠르게 추가하고 EndUpdate 메서드가 "finally" 블록 내에 호출되는 방법을 인식하여 다시 칠하기가 올바르게 완료되었는지 확인할 수 있습니다.


void UpdateGrid(C1FlexGrid c1FlexGrid1)
{
   // suspend painting to avoid flicker
   c1FlexGrid1.BeginUpdate();
   c1FlexGrid1.Rows.Count = 1;
   for (int i = 1; i < 1000000; i++)
   c1FlexGrid1.AddItem("Row " + i.ToString());
   // always restore painting
   c1FlexGrid1.EndUpdate()
}



AutoResize 속성을 False로 유지


새 데이터를 데이터 소스에서 읽고 테두리 그리드의 AutoResize 속성이 true로 설정된 경우 컨트롤은 가장 넓은 항목에 맞추도록 열의 크기를 자동으로 조정합니다. 데이터 소스에 많은 행과 열이 있는 경우 자동 크기 조정은 시간이 오래 걸릴 수 있습니다. 이러한 상황에서는 자동 크기 조정을 비활성화하고 소스 코드에서 바로 열 너비를 조정해볼 수 있습니다.



동적으로 스타일 할당


FlexGrid는 행, 열 및 임의의 셀 범위에 대한 셀 스타일을 생성하고 할당할 수 있습니다. 이 기능을 사용하면 특정 조건을 기반으로 그리드 셀의 모양을 변경할 수 있습니다. 일반적으로 이를 위해서는 SetCellStyle() 메서드를 사용하지만 이 경우에는 셀 값이 변경될 때마다 스타일을 변경해야 했습니다. 그리드가 데이터 소스에 연결된 경우 데이터 소스가 데이터 정렬 또는 필터링과 같은 작업을 따라 재설정되면 스타일이 손실됩니다.


OwnerDrawCell 이벤트는 각 셀이 렌더링되는 방식을 수정하거나 그림을 전체적으로 재정의하는 데 사용됩니다.

private void Form1_Load(object sender, EventArgs e)
{
  // Fill a column with random values.
     c1FlexGrid1.Cols[1].DataType = typeof(int);
     Random rnd = new Random();
     for (int r = 1; r < c1FlexGrid1.Rows.Count; r++)
      {
         c1FlexGrid1[r, 1] = rnd.Next(-10000, 10000);
      }
 
  // Create style used to show negative values.
     c1FlexGrid1.Styles.Add("Red").ForeColor = Color.Red;
 
  // Enable OwnerDraw by setting the DrawMode property.
     c1FlexGrid1.DrawMode = C1.Win.C1FlexGrid.DrawModeEnum.OwnerDraw;
     c1FlexGrid1.OwnerDrawCell += new C1.Win.C1FlexGrid.OwnerDrawCellEventHandler(C1FlexGrid1_OwnerDrawCell);
}

private void C1FlexGrid1_OwnerDrawCell(object sender, OwnerDrawCellEventArgs e)
{
   if(!e.Measuring)
  {
       // Check that the row and column contain integer data.
       if (e.Row > 0 && c1FlexGrid1.Cols[e.Col].DataType == typeof(int))
      {
          // Apply the style "Red"
          e.Style = c1FlexGrid1.Styles["Red"];
      }
  }
}



OwnerDrawCell 이벤트에서 스타일 수정 피하기


효율성을 높이는 또다른 옵션은 OwnerDrawCell 이벤트에서 매개 변수로 공급되는 CellStyle 개체 수정을 피하는 것입니다. 대안으로 e.Style 옵션을 새 값으로 변경할 수 있습니다. 이벤트 처리기에서 반환한 CellStyle은 다른 셀에서 자주 사용되므로 이는 중요합니다.


예를 들어 WinForms FlexGrid의 보통 스타일을 잘못 변경하여 그리드의 다른 유사한 셀에 영향을 줄 수 있습니다.

// ** CORRECT APPROACH:
private void C1FlexGrid1_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
   // Select style to use when painting this cell:
   e.Style = MyStyleSelector(e.Row, e.Col);
}
                                               
// ** WRONG APPROACH:
private void C1FlexGrid1_OwnerDrawCell(object sender, C1.Win.C1FlexGrid.OwnerDrawCellEventArgs e)
{
   // Select style to use when painting this cell:
   // This is wrong because changing any CellStyle objects invalidates the
   // grid, which would cause this event handler to be called over and
   // over again.
   e.Style.Color = MyColorSelector(e.Row, e.Col);
}



단일 열에서 타원 표시


로드할 데이터의 양이 짧은 경우 그리드는 빠르게 그리므로 긴 문자열 값의 경우 열 너비에 따라 끝에 타원 기호를 간단하게 표시합니다. 그리드의 단일 열에서 타원을 확인하려면 자르기 속성을 활용해야 합니다. 자르기 속성은 셀에 맞추도록 자를 문자열의 길이를 정의하기 위해 None, Character, Word, EllipsisCharacter, EllipsisWord 또는 EllipsisPath로 설정할 수 있습니다.


WinForms FlexGrid 열의 끝에 타원을 표시하려면 자르기 속성을 다음과 같이 설정해야 합니다.

c1FlexGrid1.Cols[columnIndex].StyleNew.Trimming =StringTrimming.EllipsisCharacter;



셀에서 여러 줄 텍스트 표시


WordWrap높이 속성을 사용하여 단일 셀에서 많은 줄이 있는 텍스트를 표시할 수 있습니다. 그리드가 공백이 있는 긴 문자열을 여러 줄로 나눌지 여부를 결정하기 위해 WordWrap 속성이 사용됩니다.


아래 코드를 참조하여 여러 줄이 있는 텍스트를 WinForms FlexGrid에서 효율적으로 표시하는 방법을 확인하십시오.

// Set the WordWrap property.
c1FlexGrid1.Styles["Normal"].WordWrap = true;
 
// Set the row height.
c1FlexGrid1.Rows[1].Height = 2 * fg.Rows.DefaultSize;
 
// Add text to the cell.
c1FlexGrid1[1, 2] = "This is the first line. \r\n This is the second line.";



데이터 표에 바인딩되는 경우 데이터 정렬 가져오기


런타임에서 정렬 식을 설정하면 데이터 보기에서 변경 사항이 반영됩니다. 이 경우 기본 보기의 정렬 특성과 정렬 식을 활용할 수 있습니다. 정렬 속성은 열 이름 및 ASC(기본값) 또는 DESC가 있는 문자열을 사용하여 오름차순 또는 내림차순으로 열을 정렬합니다. 쉼표로 열 이름을 구분하면 여러 열을 정렬할 수 있습니다.


아래 코드는 WinForms FlexGrid에서 정렬 속성으로 정렬 식을 사용하는 방법을 표시합니다.

// Sort the data by the UnitsInStock column then by the ProductID column.
  this.productsBindingSource.Sort = "UnitsInStock ASC, ProductID ASC";



UseScrollWindow 속성 사용


ScrollWindow 기능을 사용하면 지금 스크롤하고 있는 셀만 스크롤하고 다시 그릴 때 더티 데이터가 있는 셀만 다시 그릴 수 있습니다.

스크롤 성능을 상당히 개선하려면 이 속성의 값은 True여야 하며 이는 기본적으로 설정되므로 활성화를 위해 추가 코드를 사용할 필요가 없습니다.

시각적 아티팩트가 복잡한 OwnerDraw와 발생할 수 있는 몇 가지 시나리오가 있을 수 있으며 여기서 다른 컨트롤 또는 이미지가 FlexGrid 상단에 그려집니다.


따라서 이 경우에는 아래에 표시된 대로 보호된 속성 UseScrollWindow를 설정하여 비활성화해야 합니다.

public class MyFlexGrid : C1FlexGrid
{
  public MyFlexGrid()
  {
     UseScrollWindow = false;
  }
}


FlexGrid 렌더가 더 빨라지도록 이에 따라 프로젝트에서 위에 제공된 모든 접근 방식을 구현할 수 있습니다. C1FlexGrid 컨트롤로 제공된 최적화 기능을 활용해보시길 바랍니다.




지금 바로 ComponentOne을 다운로드하여 직접 테스트해보세요!

 
  • 페이스북으로 공유
  • 트위터로  공유
  • 링크 복사
  • 카카오톡으로 보내기

댓글목록

등록된 댓글이 없습니다.

메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기

태그1

인기글

더보기
  • 인기 게시물이 없습니다.
메시어스 홈페이지를 통해 제품에 대해서 더 자세히 알아 보세요!
홈페이지 바로가기
이메일 : sales-kor@mescius.com | 전화 : 1670-0583 | 경기도 과천시 과천대로 7길 33, 디테크타워 B동 1107호 메시어스(주) 대표자 : 허경명 | 사업자등록번호 : 123-84-00981 | 통신판매업신고번호 : 2013-경기안양-00331 ⓒ 2024 MESCIUS inc. All rights reserved.