첨부 소스 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

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
    }
}

 

728x90

 

▶ 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
    }
}

 

300x250

 

▶ 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
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요