c# winform datagridview单元格合并

效果

 

 

/// <summary>
    /// DataGridView 单元格合并信息
    /// </summary>
    public struct DataGridViewMergeCellRegion
    {

        public int FromRowIndex { get; set; }

        public int FromColIndex { get; set; }

        public int ToRowIndex { get; set; }

        public int ToColIndex { get; set; }
    }

 

 

 public class DataGridViewMergeColumn : DataGridViewColumn
    {

        public DataGridViewMergeColumn()
            : base(new DataGridViewMergeCell())
        {

        }

        public DataGridViewMergeColumn(DataGridViewCell cell)
            : base(cell)
        {

        }

        /// <summary>
        /// 是否是进度
        /// </summary>
        public bool IsJingDu { get; set; }
    }

    /// <summary>
    /// 如果列隐藏会有bug
    /// </summary>
    public class DataGridViewMergeCell : DataGridViewCell
    {


        int GetMergeWidth(bool all, DataGridViewMergeCellRegion reg)
        {

            int w = 0, lindex = reg.FromColIndex, lend = all ? reg.ToColIndex + 1 : this.ColumnIndex;
            int rowindex = this.RowIndex;
            DataGridViewCell cell;
            while (lindex < lend)
            {
                cell = this.DataGridView.Rows[rowindex].Cells[lindex];
                w += cell.Size.Width;
                lindex += 1;
            }
            return w;
        }
        int GetMergeHeight(bool all, DataGridViewMergeCellRegion reg)
        {

            int w = 0, lindex = reg.FromRowIndex, lend = all ? reg.ToRowIndex + 1 : this.RowIndex;
            int colindex = this.ColumnIndex;
            DataGridViewCell cell;
            while (lindex < lend)
            {
                cell = this.DataGridView.Rows[lindex].Cells[colindex];
                w += cell.Size.Height;
                lindex += 1;
            }
            return w;
        }


        protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context)
        {
            if (value == null || value == DBNull.Value || string.IsNullOrEmpty(cellStyle.Format))
            {
                if (value == null || value == DBNull.Value)
                    return "";
                return base.GetFormattedValue(value, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
            }
            return String.Format("{0:" + cellStyle.Format + "}", value);
        }

        protected override void Paint(System.Drawing.Graphics graphics, System.Drawing.Rectangle clipBounds, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts)
        {


            if (this.ColumnIndex == -1 || rowIndex == -1)
            {
                base.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts);
                return;
            }

            bool isselect = (cellState & DataGridViewElementStates.Selected) == DataGridViewElementStates.Selected;


            DataGridViewMergeCellRegion? mergeinfo = this.DataGridView.GetMergeCellRegion(rowIndex, this.ColumnIndex);
            DataGridViewCell mergebegcell = null;
            //合并
            if (mergeinfo != null)
            {
                DataGridViewMergeCellRegion reg = mergeinfo.Value;

                DataGridViewCell cell = this.DataGridView.Rows[reg.FromRowIndex].Cells[reg.FromColIndex];
                value = cell.Value;
                formattedValue = cell.FormattedValue;
                mergebegcell = cell;


                int lrowindex = reg.FromRowIndex, lcolindex;

                cellBounds.X -= GetMergeWidth(false, reg);
                cellBounds.Y -= GetMergeHeight(false, reg);
                cellBounds.Width = GetMergeWidth(true, reg);
                cellBounds.Height = GetMergeHeight(true, reg);


                while (lrowindex <= reg.ToRowIndex)
                {
                    lcolindex = reg.FromColIndex;
                    while (lcolindex <= reg.ToColIndex)
                    {
                        cell = this.DataGridView.Rows[lrowindex].Cells[lcolindex];

                        cell.Selected = isselect;

                        lcolindex += 1;
                    }
                    lrowindex += 1;
                }


            }

            SolidBrush backBrush = new SolidBrush(isselect ? cellStyle.SelectionBackColor : cellStyle.BackColor);

            Pen pen = new Pen(this.DataGridView.GridColor);


            //画边框
            graphics.DrawRectangle(pen, cellBounds.X - 1, cellBounds.Y - 1, cellBounds.Width, cellBounds.Height);

            Rectangle rt = new Rectangle(cellBounds.X, cellBounds.Y, cellBounds.Width - 1, cellBounds.Height - 1);
            //填充背景
            graphics.FillRectangle(backBrush, rt);

            PaintData(graphics, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, isselect, mergebegcell);
            backBrush.Dispose();
            pen.Dispose();

        }

        /// <summary>
        /// 画数据
        /// </summary>
        protected virtual void PaintData(System.Drawing.Graphics graphics, System.Drawing.Rectangle cellBounds, int rowIndex, DataGridViewElementStates cellState, object value, object formattedValue, string errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, bool isselect, DataGridViewCell mergebegcell)
        {
            string strvalue = null;
            if (formattedValue != null)
                strvalue = formattedValue.ToString();
            if (strvalue == null && value != null)
                strvalue = value.ToString();

            if (!isselect && ((this.OwningColumn as DataGridViewMergeColumn).IsJingDu || (mergebegcell != null && (mergebegcell.OwningColumn as DataGridViewMergeColumn).IsJingDu)))
            {

                decimal val;
                if (value != null && value != DBNull.Value && decimal.TryParse(value.ToString(), out val))
                {

                    if (formattedValue == null)
                        strvalue = val.ToString("0.00%");

                    if (val != 0)
                    {
                        //填充背景
                        Rectangle rt = new Rectangle(cellBounds.X + 1, cellBounds.Y + 1, (int)((cellBounds.Width - 3) * val), cellBounds.Height - 3);
                        if (rt.Width > cellBounds.Width)
                            rt.Width = cellBounds.Width - 3;
                        Color FColor = Color.FromArgb(105, 193, 137); //颜色1
                        Color TColor = Color.FromArgb(225, 244, 231);  //颜色2 
                        Brush lbackBrush = new LinearGradientBrush(rt, FColor, TColor, LinearGradientMode.Horizontal);
                        graphics.FillRectangle(lbackBrush, rt);
                        lbackBrush.Dispose();
                    }
                }
            }

            if (strvalue != null && strvalue != "")
            {
                SolidBrush fontBrush = new SolidBrush(isselect ? cellStyle.SelectionForeColor : cellStyle.ForeColor);
                SizeF sizef = graphics.MeasureString(strvalue, cellStyle.Font);
                int fontheight = (int)sizef.Height;
                int fontwidth = (int)sizef.Width;

                int preheight = ((cellBounds.Height - 2) - fontheight) / 2;
                int prewidth = ((cellBounds.Width - 2) - fontwidth) / 2;

                float x = cellBounds.X + 1 + prewidth, y = cellBounds.Y + 1 + preheight;


                graphics.DrawString(strvalue, cellStyle.Font, fontBrush, x, y);
                fontBrush.Dispose();
            }

        }

    }
 

  public static class DataGridViewExtend
    {

        static Dictionary<DataGridView, List<DataGridViewMergeCellRegion>> dic = new Dictionary<DataGridView, List<DataGridViewMergeCellRegion>>();

        /// <summary>
        /// 添加合并
        /// </summary>
        /// <param name="dg"></param>
        /// <param name="fromrowindex">开始行Index</param>
        /// <param name="fromcolindex">开始列Index</param>
        /// <param name="torowindex">目的行Index</param>
        /// <param name="tocolindex">目的列Index</param>
        public static void AddMerge(this  DataGridView dg, int fromrowindex, int fromcolindex, int torowindex, int tocolindex)
        {

            if (fromrowindex == -1 || fromcolindex == -1 || torowindex == -1 || tocolindex == -1)
            {
                return;
            }
            int lrowindex = fromrowindex, lcolindex = fromcolindex;
            if (fromrowindex > torowindex)
            {
                fromrowindex = torowindex;
                torowindex = lrowindex;
            }

            if (fromcolindex > tocolindex)
            {
                fromcolindex = tocolindex;
                tocolindex = lcolindex;
            }

            if (torowindex + 1 > dg.Rows.Count)
            {
                throw new Exception("目的行Index超过DataGridView行数");
            }
            if (tocolindex + 1 > dg.ColumnCount)
            {
                throw new Exception("目的列Index超过DataGridView列数");
            }

            if (fromrowindex == torowindex && fromcolindex == tocolindex)
            {
                return;
            }

            List<DataGridViewMergeCellRegion> list;

            if (!dic.TryGetValue(dg, out list))
            {
                dg.Disposed += dg_Disposed;
                dg.DataSourceChanged += dg_DataSourceChanged;
                dg.RowHeightChanged += dg_RowHeightChanged;
                dg.ColumnWidthChanged += dg_ColumnWidthChanged;
                list = new List<DataGridViewMergeCellRegion>();
                dic.Add(dg, list);
            }

            DataGridViewMergeCellRegion reg = new DataGridViewMergeCellRegion();
            reg.FromColIndex = fromcolindex;
            reg.FromRowIndex = fromrowindex;
            reg.ToColIndex = tocolindex;
            reg.ToRowIndex = torowindex;
            list.Add(reg);
        }

        static void dg_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
        {
            DataGridView dg = sender as DataGridView;
            List<DataGridViewMergeCellRegion> list;
            if (dic.TryGetValue(dg, out list))
            {
                var colindex = e.Column.Index;
                foreach (DataGridViewMergeCellRegion reg in list)
                {
                    if (colindex >= reg.FromColIndex && colindex <= reg.ToColIndex)
                    {
                        int begrow = reg.FromRowIndex;
                        while (begrow <= reg.ToRowIndex)
                        {
                            int begcol = reg.FromColIndex;
                            while (begcol <= reg.ToColIndex)
                            {
                                if (begcol != colindex)
                                {
                                    dg.InvalidateCell(begcol, begrow);
                                }
                                begcol += 1;
                            }
                            begrow += 1;
                        }
                    }
                }
            }
        }

        static void dg_RowHeightChanged(object sender, DataGridViewRowEventArgs e)
        {
            DataGridView dg = sender as DataGridView;
            List<DataGridViewMergeCellRegion> list;
            if (dic.TryGetValue(dg, out list))
            {
                var rowindex = e.Row.Index;
                foreach (DataGridViewMergeCellRegion reg in list)
                {
                    if (rowindex >= reg.FromRowIndex && rowindex <= reg.ToRowIndex)
                    {
                        int begrow = reg.FromRowIndex;

                        while (begrow <= reg.ToRowIndex)
                        {
                            if (rowindex != begrow)
                            {
                                int begcol = reg.FromColIndex;
                                while (begcol <= reg.ToColIndex)
                                {
                                    dg.InvalidateCell(begcol, begrow);
                                    begcol += 1;
                                }
                            }
                            begrow += 1;
                        }
                    }
                }

            }
        }

        static void dg_DataSourceChanged(object sender, EventArgs e)
        {
            dg_Disposed(sender, null);
        }

        /// <summary>
        /// 获取单元格合并信息
        /// </summary>
        /// <param name="dg"></param>
        /// <param name="fromrowindex"></param>
        /// <param name="fromcolindex"></param>
        /// <returns></returns>
        public static DataGridViewMergeCellRegion? GetMergeCellRegion(this  DataGridView dg, int rowindex, int colindex)
        {
            List<DataGridViewMergeCellRegion> list;
            if (dic.TryGetValue(dg, out list))
            {
                foreach (DataGridViewMergeCellRegion reg in list)
                {
                    if (rowindex >= reg.FromRowIndex && rowindex <= reg.ToRowIndex && colindex >= reg.FromColIndex && colindex <= reg.ToColIndex)
                        return reg;
                }
            }
            return null;
        }

        /// <summary>
        /// 清除合并的单元格信息
        /// </summary>
        /// <param name="dg"></param>
        public static void ClearMerge(this  DataGridView dg)
        {
            dg_Disposed(dg, null);
        }

        static void dg_Disposed(object sender, EventArgs e)
        {
            DataGridView dg = sender as DataGridView;
            List<DataGridViewMergeCellRegion> list;
            if (dic.TryGetValue(dg, out list))
            {
                list.Clear();
                dic.Remove(dg);
            }
        }
    }

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值