반응형

WANIGridDataTableDataSource에 할당하는 방법에 대해서 알아보자.

보통 우리는 데이터베이스에서 쿼리를 통해서 우리가 원하는 데이터들을 DataTable에 담아서 가져오게 되고, 이렇게 가져온 데이터를 특정한 양식 또는 원하는 화면에 사용자에게 제공하게 된다.

WANIGrid 또한 이렇게 가져온 데이터인 DataTable를 할당함으로써 WANIGrid에 원하는 컬럼의 정보들을 모두 제공할 수 있게 된다.

 

첨부된 WANIGridExample 프로젝트의 WANIGridExample.cs파일을 열어서 GridInitialize() 메소드를 살펴보자. WANIGrid를 사용하기 위해서는 항상 WANIGridHeader Column을 정의하고 WANIGrid에서 보여주고자 하는 DataTable의 정보를 할당하면 된다.

GridInitialize 메소드의 내부를 하나씩 살펴보기로 하자.

 

HeaderColumn 클래스의 List를 선언하고 waniGrid.TopHeaderList.GetHeaderList() 메소드를 호출해서 빈 headerColumns List를 생성한다.

List<HeaderColumn> headerColumns = waniGrid.TopHeaderList.GetHeaderList();

List<HeaderColumn> headerColumns를 새로 생성한다. Index 값이 0이고 ColumnId“LeftHeader”인 빈 컬럼 1개만 생성됨. 이 후에 각 컬럼들을 추가한다.

 

HeaderColumn 클래스의 속성과 메소드를 잠깐 살펴보자.

속성(Property)

get/set

상세

public int Index

get/set

컬럼 인덱스

public string ColumnId

get/set

컬럼 ID. DataTableColumn Name과 동일해야 함

public string Title

get/set

컬럼 헤더의 명칭.

public int Left

get/set

컬럼의 Left 즉 시작하는 X좌표 값

public int Width

get/set

컬럼의 폭

public HorizontalAlignment HeadAlign

get/set

컬럼 헤더 명칭의 정렬 방법

public HorizontalAlignment TextAlign

get/set

컬럼 데이터의 정렬 위치. DataTableRow별 컬럼 ID에 해당하는 데이터 값을 의미

public bool Visible

get/set

화면에서 해당 컬럼을 화면에 Display 여부. true면 보여지고 false인 경우 숨겨짐.

public bool Editable

get/set

컬럼의 데이터 편집 여부. true면 편집 가능 그렇지 않으면 편집 불가

public bool IsCalendar

get/set

컬럼이 날짜 정보를 가지고 있으면 true, 그렇지 않으면 false

public ViewRange

ViewRange

get/set

컬럼의 시작 X좌표와 끝 X좌표 값을 가지고 있는 ViewRange 타입.

 

WANIGrid를 초기화 하는 방법은 Header 영역을 초기화하고, Header영역의 컬럼들을 정의하는 것으로 일차적인 초기화를 하게된다.

Header영역을 Clear하고 HeaderColumn 목록을 초기화한다.

List<HeaderColumn> headerColumns = waniGrid.TopHeaderList.GetHeaderList();

DataTable의 각 컬럼명과 ColumnId를 동일하게 부여하면 DataTableColumn 값이 WANIGrid의 컬럼에 표시되게 된다.

headerColumns.Add(new HeaderColumn() { ColumnId = "Col01", Title = "Column 01", Width = 80, HeadAlign = HorizontalAlignment.Center, TextAlign = HorizontalAlignment.Left, Editable = true, Visible = true });

headerColumns ListHeaderColumn을 추가하면서 컬럼들을 하나씩 설정해 나가면 된다.

  • ColumnId DataTableColumn명과 동일하게 부여하면 DataTableColumn 값을 할당하게 된다.
  • Title WANIGrid의 컬럼 헤더에 표시되는 텍스트
  • Width 컬럼의 폭을 지정한다.
  • HeadAlign 헤더의 표시되는 텍스트 정렬 방법
  • TextAlign Column 값의 정렬 방법
  • Editable 편집 여부
  • Visible 화면에 표시 여부

컬럼의 속성을 설정해서 headerColumns 리스트를 waniGrid 컨크롤에 할당한다.

waniGrid.TopHeaderList.SetHeaderList(headerColumns);

WANIGrid 컨트롤에 할당한 컬럼 정보들을 InitializeHeader 메소드를 호출해서 초기화한다.

waniGrid.InitializeHeader();

WANIGrid 컨트롤에 고정 컬럼의 개수를 지정할 경우 FixedCol 속성에 고정 컬럼의 개수를 지정한다. 기본 값은 0이다.

waniGrid.FixedCol = 0;

 

아래의 첨부 파일을 실행하면 하기와 같은 화면을 볼 수 있다.

[그림 2-1] WANIGridExample 실행화면

고정컬럼 개수를 변화시켜 보라. 고정컬럼의 영역이 무엇을 의미하는지 확인할 수 있을 것이다.

고정컬럼 수정을 체크했을 때 고정컬럼 영역을 클릭해보라. 값을 입력할 수 있는 텍스트 입력 컨트롤이 활성화 될 것이다.

행간격을 높이거나 줄여보라. 행 높이의 기본 값은 20이다.

DataTable에서 Data 가져오기 버튼을 클릭해 보라. 내부적으로 DataTable을 생성해서 생성된 DataTableWANIGridDataSource에 할당하면 아래의 같이 각 필드의 값이 DataTable의 값으로 채워지게 된다.

자세한 내용은 아래의 첨부된 소스를 참조해 보기 바란다.

 

WANIGridExample_20200514.zip
0.21MB
WANIGrid.dll
0.05MB

 

 

반응형

'WinForm > WANIGrid 컨트롤 공개' 카테고리의 다른 글

WANIGrid Control 개선 - Mouse Wheel 처리 추가  (0) 2021.04.13
WANIGrid Control 개선  (0) 2021.04.10
WANIGrid Control 사용법 1  (1) 2020.04.30
반응형

그 동안 찾아온 게으름이란 녀석 때문에 한 동안 WANI Grid Control의 소스를 꽤나 멀리했다.

근자에 바빴던 필자의 본업으로 인해 정신적 시간적 여유가 없어서 소스 보면서 어느 부분을 좀 더 개선하면 보다 쓸만한 녀석으로 바꿀 수 있을지에 대한 생각을 해보지 못했다.

2019년 한 해를 보내며 지금 작성한 이글이 2019년 마지막 글이 될지도 모르겠다.

 

오늘 추가 및 개선해 볼 기능은 특정 Column선택 시 표시되는 부분과 행(Row) 숨기기 및 숨기기 해제 기능을 추가해 볼 것이다.

 

기존의 특정 컬럼 선택 시 표현 되는 부분은 아래의 이미지와 같다.

[그림 25-1] 기존 컬럼 선택 시 표현 방법

선택된 컬럼의 행(Row)를 표기 하기 위해 LightCyan으로 표시하고 Dot선으로 Retangle을 그려서 표시를 해주고 있지만 눈으로 식별되는 부분이 약한 듯 해서 선택된 Rectangle 부분의 색상을 바탕색과 동일한 색상으로 표기를 하고자 한다.

개선한 컬럼 선택 부분은 아래의 이미지를 참고하자.

[그림 25-2] 개선된 컬럼 선택 표현 방법

사용자 좀 더 정확하게 선택한 컬럼을 식별하기가 쉽도록 개선되었다.

이 부분을 보완하기 위해서는 WANIGrid.Event.cs 파일을 열어서 Paint 영역에서 호출되는 메소드의 위치와 DrawActiveCell 메소드의 내용을 보완하면 된다.

    private void WANIGrid_Paint(object sender, PaintEventArgs e)
    {
        CalcVisibleRange();
        ReCalcScrollBars();
        DrawBackground(e.Graphics, rc);            
        DrawHeaders(e.Graphics, rc, colFixed, fixedColEditable);
        DrawActiveCell(e.Graphics);
        DrawContent(e.Graphics, rc, this.ClientRectangle.Width);            
    }

 

기존의 마지막에 위치해 있던 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;
 

             //파선 패턴 설정
            float[] dashValues = { 1, 1, 1, 1 };
            Pen grayPen = new Pen(Color.Gray, 1);
            grayPen.DashPattern = dashValues;
            g.FillRectangle(new SolidBrush(SystemColors.ControlLightLight), GetSelectedCellRect(ActiveCell.Row, ActiveCell.Col));
            g.DrawRectangle(grayPen, GetSelectedCellRect(ActiveCell.Row, ActiveCell.Col));
        }
    }

 

행(Row) 숨기기 기능을 추가하기 위해서는 한개의 행(Row) 정보를 담당하는 Row 클래스에 행 숨기기 정보를 관리하기 위한 변수를 추가해야 한다.

Row.cs 파일을 열어서 bool 타입의 hidden 변수와 Hidden Property를 선언 및 정의하기로 한다.

    private bool hidden = false;

    public bool Hidden
    {
        get { return hidden; }
        set { hidden = value; }
    }

행을 숨기고자 할 경우 Row 클래스의 hidden 변수에 true를 설정하고, 숨기기 취소를 할 경우 false를 설정하면 된다.

 

Context Menu에 선택한 행들을 모두 숨기기 처리하기 위한 메뉴와 숨기기 처리된 모든 행을 숨기기 취소하는 메뉴를 추가하도록 한다.

 

기존의 행을 그리던 모든 메소드에 행(Row)을 관리하던 컬렉션인 rows 변수의 해당 행의 row의 hidden 변수가 true일 경우 해당 행을 그리지 않고 Skip할 수 있도록 if (rows[i].hidden) continue;  부분을 모두 추가해 주면 된다.

다국어 처리를 위해 Resources폴더 내의 LanguageResource.ko-KR.resx, LanguageResource.resx 파일을 열어서 메뉴 명칭을 추가한다.

Row.Hidden : 행 숨기기/Row Hide, Row.HiddenCancel : 행 숨기기 취소/Cancel Row Hide

    private void InitializeContextMenu()
    {
        rightClickMenu = new ContextMenu();
        rightClickMenu.MenuItems.Add(LanguageResource.Row_Before_Insert);
        rightClickMenu.MenuItems.Add(LanguageResource.Row_After_Insert);
        rightClickMenu.MenuItems.Add(LanguageResource.Row_Append);
        rightClickMenu.MenuItems.Add(LanguageResource.Row_Delete);
        rightClickMenu.MenuItems.Add(LanguageResource.Row_Hidden);
        rightClickMenu.MenuItems.Add(LanguageResource.Row_HiddenCancel);

        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 를 살펴보기 바란다.

 

특별히 어려운 내용이 없는 관계로 변경 및 보완/추가된 영역을 알려 주었으니, 첨부한 소스 코드들을 참고해서 변경된 내용들을 참고하기 바란다.

 

WANI Grid_20191225.zip
0.74MB

반응형
반응형

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 화면은 아래와 같다.

아래의 테스트 화면에 대한 사용 설명은 다음 시간에 간단히 정리하도록 하겠다.

[그림 24-1] WANIGrid Test 화면

 

그외에도 가로/세로 스크롤바를 재계산하는 ReCalcScrollBars메소드의 오류 영역을 보완했고, 자잘한 버그들을 찾아서 조치했다.

이 부분은 직접 소스를 참조하도록 하자. 

 

WANI Grid_20191009.zip
0.55MB

 

 

 

 

 

반응형
반응형

Grid란 격자 모양을 의미하며, 격자 모양의 공간 즉 Cell 내부에 데이터를 보여주거나 입력하게 되는 컨트롤을 의미한다.

인터넷 상에는 Grid Control과 관련된 많은 소스와 방법들이 있다.

이미 많이 구현되어져 있고, 지금까지 내가 많이 사용해 왔던 Control이기에 앞으로 기본 기능부터 하나씩 구현하면서 점차 고유의 기능을 덧붙이고 기존의 방법과는 다른 방법을 제공하거나 제공되지 않았던 기능을 추가하면서 Grid Control을 발전시켜 나갈 계획이다.

가장 단순한 기능 부터 개발하면서 하나씩 기능을 추가해보는 경험을 함으로써 Windows Control 개발에 대한 경험과 고민, 생각들을 정리하고 이 글을 읽는 독자들과 함께 공유하고자 한다.

 

단계별로 하나씩 개발하면서 생각했던 사항과 구현된 소스를 같이 리뷰하며 보다 나은 방법을 고민하는 시간을 가질 수 있을 것으로 생각한다.

 

먼저  Grid Control에 대한 기본 구성은 

  • 헤더(Header) - Column에 대한 타이틀
  • Cell - 특정 Row와 Column으로 선택된 영역
  • 컬럼(Column) - 헤더(Header)에 종속되는 영역
  • 로우(Row) - 컬럼(Column)들로 구성된 하나의 행

으로 정의할 수 있다.

 

먼저 Grid Control의 Layout를 만들기 위해서 필요한 사항 부터 정리를 해보자.

  1. User Control을 생성 (WANIGrid)
  2. User Control에 데이터가 Grid Control 사이즈를 초과할 경우 필요한 VScrollBar와 HScrollBar 추가
  3. Control 사이즈에 맞추어 VScrollBar와 HScrollBar가 Bottom과 Right 영역에 위치하도록 설정

앞에서 이야기한 3개의 기능을 구현하기 위한 솔루션을 만들어 보기로 하자.

1. 프로젝트 또는 솔루션 열기를 선택

2. 새 프로젝트 만들기에서 Windows Forms 컨트롤 라이브러리(.Net Framework)를 선택하고 다음 버튼을 클릭한다.

3. 새 프로젝트 구성에서 프로젝트 이름과 폴더 위치를 선택해서 만들기 버튼을 클릭.

이렇게 해서 Grid Control을 만들기 위한 솔루션 및 프로젝트 구성은 완료되었다.

 

다음 과정에서는 만들어진 User Control 상에서 VScrollBar와 HScrollBar를 위치 시켜서 만들어보기로 하자.

여기까지 만든 소스 코드는 아래의 파일을 다운로드한다.

WANI Grid.zip
0.17MB

반응형
반응형

오랜 기간 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 프로그램을 시작하는 이들에게 조금이나마 내 글이 도움이 될 수 있었으면 한다.

 

 

반응형

+ Recent posts