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 메소드를 찾아서 아래의 파란색 부분을 추가한다.
/// <summary>
/// WANIGrid의 Header 영역에서 마우스 좌측 버튼 클릭 시
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MouseLeftButtonClickInTopHeadHeight(object sender, MouseEventArgs e)
{
selectedRows.Clear();
//컬럼이 존재할 경우
if (grid.GridHeaderList.Count > 0)
{
int col = GetColFromX(e.X);
if (col < 0) return; //col값이 -1이면 처리하지 않음
//Calendar 날짜 컬럼은 선택되지 않도록 처리
if (grid.GridHeaderList[col].IsDate) return;
//Control Key를 누르지 않은 상태에서 컬럼을 선택했을 경우
if (Control.ModifierKeys != Keys.Control && Control.ModifierKeys != Keys.Shift)
{
:
:
}
:
}
:
}
Calendar 컬럼의 헤더 영역을 마우스 이동 시 컬럼 폭 조정이 되지 않도록 처리해야 한다.
WANIGrid_MouseMove 이벤트의 폭을 변경하는 영역에 해당 컬럼이 Calendar정보를 가진 컬럼인지 체크하는 부분을 추가해야 한다. 아래의 파란색 부분을 참조하자.
/// <summary>
/// Mouse Move Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WANIGrid_MouseMove(object sender, MouseEventArgs e)
{
//vSpliteLineMouseDown이 true 이면 마우스 버튼이 눌러진 상태에서 이동 중인 상태임.
if (vSpliteLineMouseDown)
{
if (Math.Abs(e.X - lastMousePoint.X) > 4) DrawVSpliteLine(new Point(e.X, e.Y));
return;
}
:
if (grid.GridHeaderList.Count > 0 && e.Y < topHeaderHeight)
{
:
//Header의 컬럼과 컬럼 간의 경계선 상에 마우스 포인트가 위치했을 경우
if (!grid.GridHeaderList[i].IsDate && (e.X > colLine - 2 && e.X < colLine + 2))
{
Cursor = Cursors.VSplit;
resizeCol = i;
if (resizeCol >= grid.GridHeaderList.Count) resizeCol = grid.GridHeaderList.Count - 1;
break;
}
:
} else
{
:
//Header의 컬럼과 컬럼 간의 경계선 상에 마우스 포인트가 위치했을 경우
if (!grid.GridHeaderList[i].IsDate && (e.X > colLine - 2 && e.X < colLine + 2))
{
Cursor = Cursors.VSplit;
resizeCol = i;
if (resizeCol >= grid.GridHeaderList.Count) resizeCol = grid.GridHeaderList.Count - 1;
break;
}
:
//Header의 컬럼과 컬럼 간의 경계선 상에 마우스 포인트가 위치했을 경우
if (!grid.GridHeaderList[i].IsDate && (e.X > colLine - 2 && e.X < colLine + 2))
{
Cursor = Cursors.VSplit;
resizeCol = i;
if (resizeCol >= grid.GridHeaderList.Count) resizeCol = grid.GridHeaderList.Count - 1;
break;
:
}
}
컬럼의 데이터 수정 시 RowCollection 타입의 rows변수의 속성인 DataRow에 값이 null일 경우에 Event 처리가 되지 않도록 한다. 아래의 파란색 부분을 추가한다.
/// <summary>
/// TextBox인 editBox의 TextChanged Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void EditBox_TextChanged(object sender, EventArgs e)
{
:
if (rows[ActiveCell.Row].DataRow == null) return;
DataRow row = rows[ActiveCell.Row].DataRow;
Header header = grid.GridHeaderList.Where(x => x.Index == ActiveCell.Col).FirstOrDefault();
if (header != null)
{
if (ActiveCell_ActvieCol > -1) row[header.ColumnId] = editBox.Text;
}
}
WANIGrid Control상에서 Control키를 누르고 + 또는 - 키를 눌렀을 때 Calendar 컬럼의 Width를 1씩 줄여서 Display하는 KeyDown 이벤트를 추가한다.
/// <summary>
/// Control Key + : 폭 넓게
/// Control Key - : 폭 좁게
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void WANIGrid_KeyDown(object sender, KeyEventArgs e)
{
if (this.grid.GridDisplayType != GridType.YearMonthWeekNoDayType) return;
if (e.Control && e.KeyCode == Keys.Add)
{
foreach(YearMonthWeekNoDayHeader header in this.grid.GridHeaderList)
{
if (header.IsDate) header.Width += 1;
}
} else if (e.Control && e.KeyCode == Keys.Subtract)
{
foreach (YearMonthWeekNoDayHeader header in this.grid.GridHeaderList)
{
if (header.IsDate) header.Width -= 1;
}
}
Invalidate();
}
WANIGrid.Method.cs파일의 추가/보완할 부분들을 살펴보자
먼저 Grid 컬럼의 Header를 생성해서 추가하는 SetHeader 메소드를 살펴보자.
추가/변경 되는 부분은 아래의 파란색 부분을 참조하자.
/// <summary>
/// Grid 컬럼의 Header를 생성해서 추가한다.
/// </summary>
/// <param name="headerBuilder"></param>
public void SetHeader(HeaderBuilder headerBuilder)
{
if (grid == null) grid = new WANI_Grid.Grid.Grid();
if (headerBuilder != null)
{
grid.HeaderGen = headerBuilder.HeaderGen;
topHeaderHeight = headerBuilder.HeaderGen.TopHeaderHeight;
grid.DicWeekDay = headerBuilder.DicWeekDay;
grid.DicMonthDay = headerBuilder.DicMonthDay;
}
grid.GridDisplayType = headerBuilder.GridDisplayType;
grid.TopHeaderHeight = headerBuilder.HeaderGen.TopHeaderHeight;
InitializeScollBar();
//dataSource가 null일 경우 Header정보를 근간으로 DataTable 생성
if (dataSource != null)
{
dataSource.Clear();
dataSource = null;
rows.Clear();
rowHeight = 0;
rowsCount = 0;
selectedCols.Clear();
selectedRows.Clear();
allRowsHeight = 0;
vScrollBar.Maximum = allRowsHeight;
firstVisibleCol = 0;
lastVisibleCol = 0;
firstVisibleRow = 0;
lastVisibleRow = 0;
}
if (dataSource == null)
{
dataSource = new DataTable();
foreach (Header hd in grid.HeaderGen.GetHeaders())
{
dataSource.Columns.Add(new DataColumn(hd.ColumnId, typeof(string)));
}
}
}
Control의 Backgroud 그리는 메소드인 DrawBackground 메소드의 추가 된 부분은 아래와 같다.
/// <summary>
/// Control의 Backgroud 그리기
/// </summary>
/// <param name="g"></param>
/// <param name="rc"></param>
private void DrawBackground(Graphics g, Rectangle rc)
{
g.DrawRectangle(new Pen(SystemColors.Control, 2), 0, 0, rc.Width, rc.Height);
rc.Inflate(-1, -1);
g.FillRectangle(new SolidBrush(SystemColors.ControlLightLight), rc);
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;
//선택된 컬럼의 Background를 그린다.
SelectedColChangeBackground(g, lastFixedCol);
//선택된 행(Row)의 Background를 그린다.
SelectedRowChangeBackground(g, lastFixedCol);
//휴일 색상을 그린다
FillHolidayBackgroundColor(g);
}
휴일 컬럼의 배경 색상을 칠하는 메소드인 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,
allRowsHeight - (rowHeight * firstVisibleRow) + 1);
}
startX += grid.GridHeaderList[i].Width;
}
}
}
Header영역을 그리는 DrawHeaders메소드에서 Parameter가 하나 더 추가 되었다. 추가된 파라미터는 고정 컬럼의 수정여부에 따라 고정 컬럼의 값을 변경 또는 변경할 수 없도록 지정하는 부분이다.
/// <summary>
/// Grid의 Header 그리기
/// </summary>
/// <param name="g"></param>
/// <param name="rc"></param>
/// <param name="colFixed"></param>
/// <param name="fixedColEditable"></param>
private void DrawHeaders(Graphics g, Rectangle rc, int colFixed, bool fixedColEditable)
{
if (grid != null)
{
grid.DrawHeader(g, rc, rc.Width, colFixed, fixedColEditable);
}
}
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;
//파선 패턴 설정
float[] dashValues = { 1, 1, 1, 1 };
Pen grayPen = new Pen(Color.Gray, 1);
grayPen.DashPattern = dashValues;
g.DrawRectangle(grayPen, GetSelectedCellRect(ActiveCell.Row, ActiveCell.Col));
}
}
지금까지의 작업으로 완성된 WANIGrid Test 화면은 아래와 같다.
아래의 테스트 화면에 대한 사용 설명은 다음 시간에 간단히 정리하도록 하겠다.
그외에도 가로/세로 스크롤바를 재계산하는 ReCalcScrollBars메소드의 오류 영역을 보완했고, 자잘한 버그들을 찾아서 조치했다.
이 부분은 직접 소스를 참조하도록 하자.
'WinForm > Grid Control 만들기' 카테고리의 다른 글
25. Row 숨기기 및 숨기기 해제하기 기능 추가 (0) | 2019.12.25 |
---|---|
23. Calendar 일자별 Column Header 그리기 (0) | 2019.10.01 |
22. 새로운 Grid 유형 추가를 위한 사전 작업 (0) | 2019.09.26 |
21. DataSource에 DataTable 할당 하기 (0) | 2019.09.16 |
20. WANIGrid Control 디자인 모드 오류 및 보완 (0) | 2019.09.06 |