WANIGrid에 DataTable을 DataSource에 할당하는 방법에 대해서 알아보자.
보통 우리는 데이터베이스에서 쿼리를 통해서 우리가 원하는 데이터들을 DataTable에 담아서 가져오게 되고, 이렇게 가져온 데이터를 특정한 양식 또는 원하는 화면에 사용자에게 제공하게 된다.
WANIGrid 또한 이렇게 가져온 데이터인 DataTable를 할당함으로써 WANIGrid에 원하는 컬럼의 정보들을 모두 제공할 수 있게 된다.
첨부된 WANIGridExample 프로젝트의 WANIGridExample.cs파일을 열어서 GridInitialize() 메소드를 살펴보자. WANIGrid를 사용하기 위해서는 항상 WANIGrid의 Header Column을 정의하고 WANIGrid에서 보여주고자 하는 DataTable의 정보를 할당하면 된다.
GridInitialize 메소드의 내부를 하나씩 살펴보기로 하자.
HeaderColumn 클래스의 List를 선언하고 waniGrid.TopHeaderList.GetHeaderList() 메소드를 호출해서 빈 headerColumns List를 생성한다.
기존의 마지막에 위치해 있던 DrawActiveCell 메소드를 WANI Grid 내의 내용을 그리는 메소드인 DrawContent 메소드 앞에 위치를 시키고 DrawActiveCell 메소드에 선택한 컬럼의 Rectangle 부분에 FillRectangle 처리를 해주면 된다.
WANIGrid.Method.cs 파일을 열어서 DrawActiveCell 메소드의 FillRectange 부분을 추가해 주면 된다.
private void DrawActiveCell(Graphics g) { if (ActiveCell.Row != -1 && ActiveCell.Col != -1) { if (ActiveCell.Col > grid.GridHeaderList.Count) return; //Calendar 날짜 컬럼은 Active Cell이 되지 않도록 처리 if (grid.GridHeaderList[ActiveCell.Col].IsDate) return;
rightClickMenu.MenuItems[0].Click += new EventHandler(OnMenu_BeforeInsertRow_Click); rightClickMenu.MenuItems[1].Click += new EventHandler(OnMenu_AfterInsertRow_Click); rightClickMenu.MenuItems[2].Click += new EventHandler(OnMenu_AppenRow_Click); rightClickMenu.MenuItems[3].Click += new EventHandler(OnMenu_DeleteRow_Click); rightClickMenu.MenuItems[4].Click += new EventHandler(OnMenu_RowHidden_Click); rightClickMenu.MenuItems[5].Click += new EventHandler(OnMenu_RowHiddenCancel_Click); }
WANIGrid.Event.cs 파일 내에 행 숨기기/숨기기 취소 이벤트 처리를 해 둔 부분과 마우스 좌측 버튼 클릭시 호출되는 MouseLeftButtonClickContents 메소드의 추가된 행(Row)의 hidden 변수가 true일 때 처리를 위해서 추가한
if (rows[row].Hidden) continue; 부분을 참고하기 바랍니다.
WANIGrid.Mehtod.cs 파일을 열어서 행(Row)의 hidden 변수가 true일 경우 화면에서 그려지지 않도록 추가한 부분 역시
if (rows[row].Hidden) continue; 이 부분이 추가되어져 있다.
소스 내의 rows[row].Hidden 이 true일 경우 화면 상에 표시 되지 않도록 처리한 부분들이다.
이 부분들을 살펴 보면 될 것이다.
추가로 선택한 행들을 숨기기 처리하거나 숨겨진 모든 행(Row)들을 숨기기 취소하는 메소드인 HideAndHideCancelRow 를 살펴보기 바란다.
특별히 어려운 내용이 없는 관계로 변경 및 보완/추가된 영역을 알려 주었으니, 첨부한 소스 코드들을 참고해서 변경된 내용들을 참고하기 바란다.
Calendar 컬럼(Column)을 표현하기 위해 사전 준비 작업과 YearMonthWeekNoDayHeader, YearMonthWeekNoDayHeaderGenerator, HeaderBuilder를 살펴 보았고, 실제 WANIGrid Control 영역을 살펴보자.
새로운 변수를 추가하기로 하자.
private int currentCol = 0; //현재 첫페이지를 저장하기 위한 변수
private SolidBrush holidayColorBrush = new SolidBrush(Color.LightSkyBlue); //휴일색상
private bool fixedColEditable = true; //고정 컬럼 수정 여부
속성(Property)설정을 아래와 같이 한다.
/// <summary> /// 휴일 색상으로 채워주는 Brush 값을 가져오거나 설정한다. /// </summary> public SolidBrush HolidayColorBrush { get { return holidayColorBrush;} set { holidayColorBrush = value; } }
/// <summary> /// 고정 컬럼 수정여부 /// </summary> public bool FixedColEditable { get { return fixedColEditable; } set { fixedColEditable = value; } }
WANIGrid 영역의 Event 처리 부분인 WANIGrid.Event.cs 파일을 추가로 보완하기로 하자.
Calendar 컬럼 영역의 헤드를 마우스 클릭 했을 때 특정 컬럼이 선택되지 않도록 처리하기 위해서 마우스 좌측 버튼이 헤더 영역에서 클릭 이벤트가 있는지 체크해야 한다.
이러한 이벤트를 잡기 위해서 MouseLeftButtonClickInTopHeadHeight 메소드를 찾아서 아래의 파란색 부분을 추가한다.
int lastFixedCol = GetLastFixedCol(); if (lastFixedCol == -1) { DrawDefaultWANIGridControl(g, rc); return; } //고정 컬럼으로 지정이 가능한 영역은 Calendar 컬럼이 아닌 경우에만 가능
//Grid의 GridHeaderList 정보를 가져와서 YearMonthHeader Type의 변환 후 GetDateTime이 DateTime.MinValue 보다 작은 경우는
//Calendar 컬럼이 아님. int enableFixCol = 0; for (int i = 0; i <= lastFixedCol; i++) { YearMonthWeekNoDayHeader yearMonthHeader = grid.GridHeaderList[i] as YearMonthWeekNoDayHeader; if (yearMonthHeader != null && yearMonthHeader.GetDateTime <= DateTime.MinValue) enableFixCol = i; } if (lastFixedCol > enableFixCol) lastFixedCol = enableFixCol;
휴일 컬럼의 배경 색상을 칠하는 메소드인 FillHolidayBackgroundColor 메소드를 추가하도록 한다.
private void FillHolidayBackgroundColor(Graphics g) { if (grid.GridDisplayType != GridType.YearMonthWeekNoDayType) return; //고정 컬럼이 없을 경우 if (colFixed == 0) { int startX = leftHeaderWidth; for (int i = firstVisibleCol; i <= lastVisibleCol; i++) { YearMonthWeekNoDayHeader yearMonthHeader = grid.GridHeaderList[i] as YearMonthWeekNoDayHeader; if (yearMonthHeader.IsHoliday) { g.FillRectangle(holidayColorBrush, startX + 1, topHeaderHeight + 1, yearMonthHeader.Width,
allRowsHeight - (rowHeight * firstVisibleRow) + 1); } startX += yearMonthHeader.Width; } } else { int startX = leftHeaderWidth + GetFixedColWidth(); for (int i = firstVisibleCol + colFixed; i <= lastVisibleCol && i < grid.GridHeaderList.Count; i++) { YearMonthWeekNoDayHeader yearMonthHeader = grid.GridHeaderList[i] as YearMonthWeekNoDayHeader; if (yearMonthHeader.IsHoliday) { g.FillRectangle(holidayColorBrush, startX + 1, topHeaderHeight + 1, yearMonthHeader.Width,
grid.GridHeaderList의 IsDate가 true인 경우에 선택된 Active Cell의 경우 Active Cell 표시가 되지 않도록 한다.
/// <summary> /// Active Cell을 표기한다. /// </summary> /// <param name="g"></param> private void DrawActiveCell(Graphics g) { if (ActiveCell.Row != -1 && ActiveCell.Col != -1) { //Calendar 날짜 컬럼은 Active Cell이 되지 않도록 처리 if (grid.GridHeaderList[ActiveCell.Col].IsDate) return;
Grid란 격자 모양을 의미하며, 격자 모양의 공간 즉 Cell 내부에 데이터를 보여주거나 입력하게 되는 컨트롤을 의미한다.
인터넷 상에는 Grid Control과 관련된 많은 소스와 방법들이 있다.
이미 많이 구현되어져 있고, 지금까지 내가 많이 사용해 왔던 Control이기에 앞으로 기본 기능부터 하나씩 구현하면서 점차 고유의 기능을 덧붙이고 기존의 방법과는 다른 방법을 제공하거나 제공되지 않았던 기능을 추가하면서 Grid Control을 발전시켜 나갈 계획이다.
가장 단순한 기능 부터 개발하면서 하나씩 기능을 추가해보는 경험을 함으로써 Windows Control 개발에 대한 경험과 고민, 생각들을 정리하고 이 글을 읽는 독자들과 함께 공유하고자 한다.
단계별로 하나씩 개발하면서 생각했던 사항과 구현된 소스를 같이 리뷰하며 보다 나은 방법을 고민하는 시간을 가질 수 있을 것으로 생각한다.
먼저 Grid Control에 대한 기본 구성은
헤더(Header) - Column에 대한 타이틀
Cell - 특정 Row와 Column으로 선택된 영역
컬럼(Column) - 헤더(Header)에 종속되는 영역
로우(Row) - 컬럼(Column)들로 구성된 하나의 행
으로 정의할 수 있다.
먼저 Grid Control의 Layout를 만들기 위해서 필요한 사항 부터 정리를 해보자.
User Control을 생성 (WANIGrid)
User Control에 데이터가 Grid Control 사이즈를 초과할 경우 필요한 VScrollBar와 HScrollBar 추가
Control 사이즈에 맞추어 VScrollBar와 HScrollBar가 Bottom과 Right 영역에 위치하도록 설정
앞에서 이야기한 3개의 기능을 구현하기 위한 솔루션을 만들어 보기로 하자.
1. 프로젝트 또는 솔루션 열기를 선택
2. 새 프로젝트 만들기에서 Windows Forms 컨트롤 라이브러리(.Net Framework)를 선택하고 다음 버튼을 클릭한다.
3. 새 프로젝트 구성에서 프로젝트 이름과 폴더 위치를 선택해서 만들기 버튼을 클릭.
이렇게 해서 Grid Control을 만들기 위한 솔루션 및 프로젝트 구성은 완료되었다.
다음 과정에서는 만들어진 User Control 상에서 VScrollBar와 HScrollBar를 위치 시켜서 만들어보기로 하자.
오랜 기간 Java와 Spring Framework으로 Web 기반의 어플리케이션을 주로 개발 및 운영을 해왔던 나로서는 C#으로 시작하는 Windows 기반의 프로그램 개발이 굉장히 생소했다.
개발 언어로만 본다면 문법과 예약어 등은 크게 어려울 것이 없었으나, Windows 기반의 경험이 신입사원 시절에 다루어본 Visual Basic 6 외에는 전무했던 상황에서 C# 언어로 Windows 기반의 WinForm 어플리케이션에서 사용하는 Control 개발 및 유지보수는 상당히 버거운 작업이었다.
1년 반 정도의 고된 시간을 보냈고 지금도 고된 시간을 버티며 하나씩 깨우쳐 나가는 나의 모습을 기록해보고자 한다.
데이터를 기반으로 시각화 된 컨트롤 객체와 그래픽 기반의 UI 생성 및 유지보수는 생소하고 낯선 영역이었기에 정말 너무나 힘든 부분이었던 것 같다.
지금은 조금 나아져서 어느 정도 이해와 왜 이렇게 해야만 하는지를 조금씩 알게 되었지만 이전에는 왜 이렇게 해야 하는지 어떻게 해야 하는지를 예측이나 가늠할 수 없었던 시기가 있었다.
나의 Windows 프로그램 개발 경험은 1997년 입사해서 Visual Basic 6 으로 개발을 시작했지만 2000년 접어 들면서 Java 기반의 Web 개발로 업무가 바뀌게 되었고 그 이후로 주욱 Java 기반의 Web 개발 및 운영을 해왔다.
개발 언어로서 Java를 25년 이상 사용해오다 2017년 하반기 부터 C#을 주요 개발 언어로 사용하기 시작했다.
이때 맡게된 시스템의 운영과 개발 업무를 시작하면서 부딪히게 되는 숱한 난관들에 얼마나 많은 좌절과 의기소침의 시간을 보냈는지 모른다.
C# 이라는 언어는 익혔지만 이걸로 뭘 할지...업무에 적용해야 하는 컨트롤들은 어떻게 만들어야 할지...상용/오픈소스 기반의 Grid Control 들은 어떻게 만들 수 있는지... 등등
숱한 궁금증과 더불어 내가 생각하는 Grid Control을 만들어 보면 어떨까하는 생각에 시작을 하게 되었다.
먼저 간단한 기능 중심의 Grid Control을 만들면서 분석/설계에 대한 내용과 향 후 개선해야 할 점 등을 정리하고 점차 개선되어져 가는 Grid Control을 소개할 예정이다.
만들어진 Grid Control 소스는 공개를 할 것이며, 누구나 자유롭게 이용할 수 있도록 할 것이다.
이 블로그는 C# 개발자로 이제 막 시작하는 초보 개발자인 내가 C#과 Windows에 대해서 익히고 생각했던 내용들을 정리하면서 나 스스로가 향상되고 있음을 느끼고 조금씩 성장하는 나의 모습의 기록이기도 하다,
이제 막 개발의 길로 들어선 초보개발자나 나와 같은 상황에서 C# 기반의 Windows 프로그램을 시작하는 이들에게 조금이나마 내 글이 도움이 될 수 있었으면 한다.