첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

■ GridControl 클래스 : 수평으로 셀 병합하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


MergeCell.cs

 

 

using DevExpress.XtraGrid.Columns;

 

namespace TestProject

{

    /// <summary>

    /// 병합 셀

    /// </summary>

    public class MergeCell

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 행 핸들

        /// </summary>

        private int rowHandle;

 

        /// <summary>

        /// 그리그 컬럼 1

        /// </summary>

        private GridColumn gridColumn1;

 

        /// <summary>

        /// 그리드 컬럼 2

        /// </summary>

        private GridColumn gridColumn2;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 행 핸들 - RowHandle

 

        /// <summary>

        /// 행 핸들

        /// </summary>

        public int RowHandle

        {

            get

            {

                return this.rowHandle;

            }

            set

            {

                this.rowHandle = value;

            }

        }

 

        #endregion

        #region 그리드 컬럼 1 - GridColumn1

 

        /// <summary>

        /// 그리드 컬럼 1

        /// </summary>

        public GridColumn GridColumn1

        {

            get

            {

                return this.gridColumn1;

            }

            set

            {

                this.gridColumn1 = value;

            }

        }

 

        #endregion

        #region 그리드 컬럼 2 - GridColumn2

 

        /// <summary>

        /// 그리드 컬럼 2

        /// </summary>

        public GridColumn GridColumn2

        {

            get

            {

                return this.gridColumn2;

            }

            set

            {

                this.gridColumn2 = value;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MergeCell(rowHandle, gridColumn1, gridColumn2)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="rowHandle">행 핸들</param>

        /// <param name="gridColumn1">그리드 컬럼 1</param>

        /// <param name="gridColumn2">그리드 컬럼 2</param>

        public MergeCell(int rowHandle, GridColumn gridColumn1, GridColumn gridColumn2)

        {

            this.rowHandle   = rowHandle;

            this.gridColumn1 = gridColumn1;

            this.gridColumn2 = gridColumn2;

        }

 

        #endregion

    }

}

 

 

MergeCellGridPainter.cs

 

 

using System;

using System.Drawing;

 

using DevExpress.Utils.Drawing;

using DevExpress.XtraGrid.Views.Grid;

using DevExpress.XtraGrid.Views.Grid.Drawing;

using DevExpress.XtraGrid.Views.Grid.ViewInfo;

 

namespace TestProject

{

    /// <summary>

    /// 병합 셀 그리드 페인터

    /// </summary>

    public class MergeCellGridPainter : GridPainter

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 커스텀 페인트 여부

        /// </summary>

        private bool isCustomPainting;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 커스텀 페인팅 여부 - IsCustomPainting

 

        /// <summary>

        /// 커스텀 페인팅 여부

        /// </summary>

        public bool IsCustomPainting

        {

            get

            {

                return this.isCustomPainting;

            }

            set

            {

                this.isCustomPainting = value;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MergeCellGridPainter(gridView)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="gridView">그리드 뷰</param>

        public MergeCellGridPainter(GridView gridView) : base(gridView)

        {

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 병합 셀 그리기 - DrawMergeCell(mergeCell, e)

 

        /// <summary>

        /// 병합 셀 그리기

        /// </summary>

        /// <param name="mergeCell">병합 셀</param>

        /// <param name="e">이벤트 인자</param>

        public void DrawMergeCell(MergeCell mergeCell, DXPaintEventArgs e)

        {

            int delta = mergeCell.GridColumn1.VisibleIndex - mergeCell.GridColumn2.VisibleIndex;

 

            if(Math.Abs(delta) > 1)

            {

                return;

            }

 

            GridViewInfo gridViewInfo = View.GetViewInfo() as GridViewInfo;

 

            GridCellInfo gridCellInfo1 = gridViewInfo.GetGridCellInfo(mergeCell.RowHandle, mergeCell.GridColumn1);

            GridCellInfo gridCellInfo2 = gridViewInfo.GetGridCellInfo(mergeCell.RowHandle, mergeCell.GridColumn2);

 

            if(gridCellInfo1 == null || gridCellInfo2 == null)

            {

                return;

            }

 

            Rectangle targetRectangle = Rectangle.Union(gridCellInfo1.Bounds, gridCellInfo2.Bounds);

 

            gridCellInfo1.Bounds        = targetRectangle;

            gridCellInfo1.CellValueRect = targetRectangle;

 

            gridCellInfo2.Bounds        = targetRectangle;

            gridCellInfo2.CellValueRect = targetRectangle;

 

            if(delta < 0)

            {

                gridCellInfo1 = gridCellInfo2;

            }

 

            Rectangle boundRectangle = gridCellInfo1.ViewInfo.Bounds;

 

            boundRectangle.Width  = targetRectangle.Width;

            boundRectangle.Height = targetRectangle.Height;

 

            gridCellInfo1.ViewInfo.Bounds = boundRectangle;

 

            GraphicsCache graphicsCache = new GraphicsCache(e);

 

            gridCellInfo1.ViewInfo.CalcViewInfo(e.Graphics);

 

            this.isCustomPainting = true;

 

            gridCellInfo1.Appearance.FillRectangle(graphicsCache, gridCellInfo1.Bounds);

 

            DrawRowCell

            (

                new GridViewDrawArgs

                (

                    graphicsCache,

                    gridViewInfo,

                    gridViewInfo.ViewRects.Bounds

                ),

                gridCellInfo1

            );

 

            this.isCustomPainting = false;

        }

 

        #endregion

    }

}

 

 

MergeCellHelper.cs

 

 

using System.Collections.Generic;

using System.Windows.Forms;

 

using DevExpress.Utils.Drawing;

using DevExpress.XtraGrid.Columns;

using DevExpress.XtraGrid.Views.Base;

using DevExpress.XtraGrid.Views.Grid;

 

namespace TestProject

{

    /// <summary>

    /// 병합 셀 헬퍼

    /// </summary>

    public class MergeCellHelper

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 그리드 뷰

        /// </summary>

        private GridView gridView;

 

        /// <summary>

        /// 병합 셀 리스트

        /// </summary>

        private List<MergeCell> mergeCellList = new List<MergeCell>();

 

        /// <summary>

        /// 병합 셀 그리드 페인터

        /// </summary>

        private MergeCellGridPainter mergeCellGridPainter;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 병합 셀 리스트 - MergeCellList

 

        /// <summary>

        /// 병합 셀 리스트

        /// </summary>

        public List<MergeCell> MergeCellList

        {

            get

            {

                return this.mergeCellList;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MergeCellHelper(gridView)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="gridView">그리드 뷰</param>

        public MergeCellHelper(GridView gridView)

        {

            this.gridView = gridView;

 

            this.mergeCellGridPainter = new MergeCellGridPainter(this.gridView);

 

            this.gridView.GridControl.Paint += gridControl_Paint;

            this.gridView.CustomDrawCell    += gridView_CustomDrawCell;

            this.gridView.CellValueChanged  += gridView_CellValueChanged;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Public

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 병합 셀 추가하기 - AddMergeCell(rowHandle, gridColumn1, gridColumn2)

 

        /// <summary>

        /// 병합 셀 추가하기

        /// </summary>

        /// <param name="rowHandle">행 핸들</param>

        /// <param name="gridColumn1">그리드 컬럼 1</param>

        /// <param name="gridColumn2">그리드 컬럼 2</param>

        /// <returns>병합 셀</returns>

        public MergeCell AddMergeCell(int rowHandle, GridColumn gridColumn1, GridColumn gridColumn2)

        {

            MergeCell mergeCell = new MergeCell(rowHandle, gridColumn1, gridColumn2);

 

            this.mergeCellList.Add(mergeCell);

 

            return mergeCell;

        }

 

        #endregion

        #region 병합 셀 추가하기 - AddMergeCell(rowHandle, columnIndex1, columnIndex2, value)

 

        /// <summary>

        /// 병합 셀 추가하기

        /// </summary>

        /// <param name="rowHandle">행 핸들</param>

        /// <param name="columnIndex1">컬럼 인덱스 1</param>

        /// <param name="columnIndex2">컬럼 인덱스 2</param>

        /// <param name="value"></param>

        public void AddMergeCell(int rowHandle, int columnIndex1, int columnIndex2, object value)

        {

            MergeCell mergeCell = AddMergeCell

            (

                rowHandle,

                this.gridView.Columns[columnIndex1],

                this.gridView.Columns[columnIndex2]

            );

 

            SetCellValue(mergeCell, value);

        }

 

        #endregion

        #region 병합 셀 추가하기 - AddMergeCell(rowHandle, gridColumn1, gridColumn2, value)

 

        /// <summary>

        /// 병합 셀 추가하기

        /// </summary>

        /// <param name="rowHandle">행 핸들</param>

        /// <param name="gridColumn1">그리드 컬럼 1</param>

        /// <param name="gridColumn2">그리드 컬럼 2</param>

        /// <param name="value"></param>

        public void AddMergeCell(int rowHandle, GridColumn gridColumn1, GridColumn gridColumn2, object value)

        {

            MergeCell mergeCell = AddMergeCell(rowHandle, gridColumn1, gridColumn2);

 

            SetCellValue(mergeCell, value);

        }

 

        #endregion

 

        #region 셀 값 설정하기 - SetCellValue(rowHandle, gridColumn, value)

 

        /// <summary>

        /// 셀 값 설정하기

        /// </summary>

        /// <param name="rowHandle">행 핸들</param>

        /// <param name="gridColumn">그리드 컬럼</param>

        /// <param name="value"></param>

        public void SetCellValue(int rowHandle, GridColumn gridColumn, object value)

        {

            if(this.gridView.GetRowCellValue(rowHandle, gridColumn) != value)

            {

                this.gridView.SetRowCellValue(rowHandle, gridColumn, value);

            }

        }

 

        #endregion

        #region 셀 값 설정하기 - SetCellValue(mergeCell, value)

 

        /// <summary>

        /// 셀 값 설정하기

        /// </summary>

        /// <param name="mergeCell">병합 셀</param>

        /// <param name="value"></param>

        public void SetCellValue(MergeCell mergeCell, object value)

        {

            if(mergeCell != null)

            {

                SetCellValue(mergeCell.RowHandle, mergeCell.GridColumn1, value);

                SetCellValue(mergeCell.RowHandle, mergeCell.GridColumn2, value);

            }

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Private

        //////////////////////////////////////////////////////////////////////////////// Event

 

        #region 그리드 컨트롤 페인트시 처리하기 - gridControl_Paint(sender, e)

 

        /// <summary>

        /// 그리드 컨트롤 페인트시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void gridControl_Paint(object sender, PaintEventArgs e)

        {

            DrawMergeCell(new DXPaintEventArgs(e));

        }

 

        #endregion

        #region 그리드 뷰 셀 커스텀 그리기 - gridView_CustomDrawCell(sender, e)

 

        /// <summary>

        /// 그리드 뷰 셀 커스텀 그리기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void gridView_CustomDrawCell(object sender, RowCellCustomDrawEventArgs e)

        {

            if(IsMergeCell(e.RowHandle, e.Column))

            {

                e.Handled = !this.mergeCellGridPainter.IsCustomPainting;

            }

        }

 

        #endregion

        #region 그리드 뷰 셀 값 변경시 처리하기 - gridView_CellValueChanged(sender, e)

 

        /// <summary>

        /// 그리드 뷰 셀 값 변경시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private void gridView_CellValueChanged(object sender, CellValueChangedEventArgs e)

        {

            SetCellValue(GetMergeCell(e.RowHandle, e.Column), e.Value);

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Function

 

        #region 병합 셀 그리기 - DrawMergeCell(e)

 

        /// <summary>

        /// 병합 셀 그리기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        private void DrawMergeCell(DXPaintEventArgs e)

        {

            foreach(MergeCell mergeCell in this.mergeCellList)

            {

                this.mergeCellGridPainter.DrawMergeCell(mergeCell, e);

            }

        }

 

        #endregion

        #region 병합 셀 구하기 - GetMergeCell(rowHandle, gridColumn)

 

        /// <summary>

        /// 병합 셀 구하기

        /// </summary>

        /// <param name="rowHandle">행 번호</param>

        /// <param name="gridColumn">그리드 컬럼</param>

        /// <returns>병합 셀</returns>

        private MergeCell GetMergeCell(int rowHandle, GridColumn gridColumn)

        {

            foreach(MergeCell mergeCell in this.mergeCellList)

            {

                if(mergeCell.RowHandle == rowHandle && (gridColumn == mergeCell.GridColumn1 || gridColumn == mergeCell.GridColumn2))

                {

                    return mergeCell;

                }

            }

 

            return null;

        }

 

        #endregion

        #region 병합 셀 여부 구하기 - IsMergeCell(rowHandle, gridColumn)

 

        /// <summary>

        /// 병합 셀 여부 구하기

        /// </summary>

        /// <param name="rowHandle">행 번호</param>

        /// <param name="gridColumn">그리드 컬럼</param>

        /// <returns>병합 셀 여부</returns>

        private bool IsMergeCell(int rowHandle, GridColumn gridColumn)

        {

            return GetMergeCell(rowHandle, gridColumn) != null;

        }

 

        #endregion

    }

}

 

 

MainForm.cs

 

 

using System.Data;

 

using DevExpress.XtraEditors;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : XtraForm

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 병합 셀 헬퍼

        /// </summary>

        private MergeCellHelper mergeCellHelper;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            this.gridView.OptionsView.ShowGroupPanel = false;

 

            this.gridControl.DataSource = GetDataTable(20);

 

            this.gridView.OptionsBehavior.ReadOnly    = true;

            this.gridView.OptionsView.ColumnAutoWidth = false;

 

            this.gridView.BestFitColumns();

 

            this.mergeCellHelper = new MergeCellHelper(this.gridView);

 

            this.mergeCellHelper.AddMergeCell(1, 1, 2, "병합 값 1");

            this.mergeCellHelper.AddMergeCell(2, 2, 3, "병합 값 2");

            this.mergeCellHelper.AddMergeCell(3, 1, 2, "병합 값 3");

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Private

 

        #region 데이터 테이블 구하기 - GetDataTable(rowCount)

 

        /// <summary>

        /// 데이터 테이블 구하기

        /// </summary>

        /// <param name="rowCount">행 수</param>

        /// <returns>데이터 테이블</returns>

        private DataTable GetDataTable(int rowCount)

        {

            DataTable dataTable = new DataTable();

 

            dataTable.Columns.Add("Value1", typeof(string));

            dataTable.Columns.Add("Value2", typeof(string));

            dataTable.Columns.Add("Value3", typeof(string));

            dataTable.Columns.Add("Value4", typeof(string));

 

            for(int i = 0; i < rowCount; i++)

            {

                dataTable.Rows.Add

                (

                    new object[]

                    {

                        $"값 {i + 1}",

                        $"값 {i + 1}",

                        $"값 {i + 1}",

                        $"값 {i + 1}"

                    }

                );

            }

 

            return dataTable;

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

Posted by 사용자 icodebroker
TAG

댓글을 달아 주세요