效果
///
/// DataGridView 单元格合并信息
///
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)
{
}
///
/// 是否是进度
///
public bool IsJingDu { get; set; }
}
///
/// 如果列隐藏会有bug
///
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();
}
///
/// 画数据
///
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
///
/// 添加合并
///
///
/// 开始行Index
/// 开始列Index
/// 目的行Index
/// 目的列Index
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
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
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
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
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);
}
///
/// 获取单元格合并信息
///
///
///
///
///
public static DataGridViewMergeCellRegion? GetMergeCellRegion(this DataGridView dg, int rowindex, int colindex)
{
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;
}
///
/// 清除合并的单元格信息
///
///
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
if (dic.TryGetValue(dg, out list))
{
list.Clear();
dic.Remove(dg);
}
}
}