842 lines
40 KiB
C#
842 lines
40 KiB
C#
using AllBase;
|
|
using NaiBa.Util;
|
|
using NaiBa.Util.Extension;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace TemuKJD.Extension
|
|
{
|
|
public static class DataGridViewExtension
|
|
{
|
|
public static object GetCellValueFromColumnName(this DataGridViewCellCollection CellCollection, string name)
|
|
{
|
|
return CellCollection.Cast<DataGridViewCell>().FirstOrDefault(c => c.OwningColumn.Name == name)?.Value;
|
|
}
|
|
|
|
public static CheckBox AddSelectorColumn(this DataGridView dgv, string columnName = "Selected", Action<DataGridViewColumn> addHeaderCheckBoxOverride = null)
|
|
{
|
|
if (dgv.Columns[columnName] == null)
|
|
{
|
|
//var dt = dgv.Table();
|
|
|
|
//var dcol = new DataColumn(columnName, typeof(bool));
|
|
//dt.Columns.Add(dcol);
|
|
|
|
//dt.ColumnChanged += (s, e) =>
|
|
//{
|
|
// var chCols = e.Row.GetChangedColumns();
|
|
// if (chCols.Count == 1 && chCols[0].Equals(dcol))
|
|
// e.Row.AcceptChanges();
|
|
//};
|
|
}
|
|
|
|
var col = dgv.Columns[columnName];
|
|
col.HeaderText = "";
|
|
col.ReadOnly = false;
|
|
if (addHeaderCheckBoxOverride != null)
|
|
{
|
|
addHeaderCheckBoxOverride(col);
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
return col.AddHeaderCheckBox();
|
|
}
|
|
}
|
|
|
|
public static CheckBox AddHeaderCheckBox(this DataGridViewColumn column, HorizontalAlignment align = HorizontalAlignment.Center, int leftBorderOffset = 0, int rightBorderOffset = 0, Func<object, bool> getValue = null, Action<object, bool> setValue = null, bool isSetCheckedChangedEvent = true, CheckBox checkBox = null, bool isClearHeaderText = false)
|
|
{
|
|
if (column?.DataGridView == null) //throw new ArgumentNullException("First you need to add the column to grid.");
|
|
MessageBox.Show("DataGridView中没有对应的CheckBox列");
|
|
|
|
// Creating checkbox without panel
|
|
if (checkBox == null)
|
|
{
|
|
checkBox = new CheckBox();
|
|
checkBox.Name = "chk" + column.Name;
|
|
}
|
|
checkBox.Size = new Size(24, 20);
|
|
checkBox.BackColor = Color.Transparent;
|
|
checkBox.Enabled = true;
|
|
|
|
// Reset properties
|
|
checkBox.Padding = new Padding(6,2,0,0);
|
|
checkBox.Margin = new Padding(0);
|
|
checkBox.Text = "";
|
|
|
|
if (isClearHeaderText)
|
|
column.HeaderText = "";
|
|
|
|
var changedByUser = true;
|
|
var dgv = column.DataGridView;
|
|
|
|
if (isSetCheckedChangedEvent)
|
|
{
|
|
checkBox.CheckedChanged += (s, e) =>
|
|
{
|
|
if (changedByUser)
|
|
{
|
|
try
|
|
{
|
|
changedByUser = false;
|
|
|
|
if (dgv.IsCurrentCellInEditMode && dgv.CurrentCell.OwningColumn.Name.Equals(column.Name))
|
|
dgv.EndEdit();
|
|
|
|
var dgvRows = new List<DataGridViewRow>((dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows).Cast<DataGridViewRow>());
|
|
dgvRows = dgvRows.Where(r => r.Visible == true).ToList();
|
|
|
|
if (column.IsDataBound)
|
|
{
|
|
//adding to list because of BindingSource sort by that column
|
|
var boundItems = new List<object>();
|
|
var areDataRows = dgvRows.Count < 1 || dgvRows[0].DataBoundItem is DataRowView;
|
|
if (areDataRows)
|
|
{
|
|
foreach (DataGridViewRow row in dgvRows)
|
|
boundItems.Add(((DataRowView)row.DataBoundItem).Row);
|
|
foreach (DataRow dr in boundItems)
|
|
{
|
|
var val = dr[column.DataPropertyName];
|
|
if ((val is bool && (bool)val) != checkBox.Checked)
|
|
dr[column.DataPropertyName] = checkBox.Checked;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (DataGridViewRow row in dgvRows)
|
|
boundItems.Add(row.DataBoundItem);
|
|
foreach (var item in boundItems)
|
|
{
|
|
var val = getValue(item);
|
|
if (val != checkBox.Checked)
|
|
setValue(item, checkBox.Checked);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (DataGridViewRow dgr in dgvRows)
|
|
{
|
|
var cell = dgr.Cells[column.Name];
|
|
if ((cell.Value is bool && (bool)cell.Value) != checkBox.Checked)
|
|
cell.Value = checkBox.Checked;
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
changedByUser = true;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// Add checkbox to datagrid cell
|
|
dgv.Controls.Add(checkBox);
|
|
|
|
Action onColResize = () =>
|
|
{
|
|
var colCheck = dgv.Columns[column.Name];
|
|
if (colCheck == null) return;
|
|
int colLeft = (dgv.RowHeadersVisible ? dgv.RowHeadersWidth : 0) - (colCheck.Frozen ? 0 : dgv.HorizontalScrollingOffset);
|
|
foreach (DataGridViewColumn col in dgv.Columns)
|
|
{
|
|
if (col.DisplayIndex >= colCheck.DisplayIndex) break;
|
|
if (!col.Visible) continue;
|
|
colLeft += col.Width;
|
|
}
|
|
|
|
var newPoint = new Point(colLeft, dgv.ColumnHeadersHeight / 2 - checkBox.Height / 2);
|
|
|
|
if (align == HorizontalAlignment.Left)
|
|
newPoint.X += 3;
|
|
else if (align == HorizontalAlignment.Center)
|
|
newPoint.X += colCheck.Width / 2 - checkBox.Width / 2;
|
|
else if (align == HorizontalAlignment.Right)
|
|
newPoint.X += colCheck.Width - checkBox.Width - 3;
|
|
|
|
var minLeft = colLeft + leftBorderOffset;
|
|
var maxLeft = colLeft + colCheck.Width - checkBox.Width + rightBorderOffset;
|
|
|
|
if (newPoint.X < minLeft) newPoint.X = minLeft;
|
|
if (newPoint.X > maxLeft) newPoint.X = maxLeft;
|
|
|
|
checkBox.Location = newPoint;
|
|
checkBox.Visible = colCheck.Visible;
|
|
};
|
|
dgv.ColumnWidthChanged += (s, e) => onColResize();
|
|
dgv.ColumnHeadersHeightChanged += (s, e) => onColResize();
|
|
dgv.Scroll += (s, e) => onColResize();
|
|
dgv.Resize += (s, e) => onColResize();
|
|
dgv.Sorted += (s, e) => onColResize();
|
|
dgv.RowHeadersWidthChanged += (s, e) => onColResize();
|
|
dgv.ColumnStateChanged += (s, e) => onColResize();
|
|
|
|
Action<object> onDataChanged = (e) =>
|
|
{
|
|
if (!changedByUser) return;
|
|
if (e is DataColumnChangeEventArgs)
|
|
{
|
|
if (!((DataColumnChangeEventArgs)e).Column.ColumnName.Equals(column.Name))
|
|
return;
|
|
}
|
|
else if (e is ListChangedEventArgs)
|
|
{
|
|
var prop = ((ListChangedEventArgs)e).PropertyDescriptor;
|
|
if (prop != null && !prop.Name.Equals(column.DataPropertyName))
|
|
return;
|
|
}
|
|
|
|
bool allAreTrue = true;
|
|
foreach (DataGridViewRow row in dgv.SelectedRows.Count < 2 ? (ICollection)dgv.Rows : dgv.SelectedRows)
|
|
{
|
|
var val = row.Cells[column.Name].Value;
|
|
if (!(val is bool) || !(bool)val)
|
|
{
|
|
allAreTrue = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
changedByUser = false;
|
|
var tag = checkBox.Tag;
|
|
checkBox.Tag = "AUTO";
|
|
try
|
|
{
|
|
if (isSetCheckedChangedEvent)
|
|
{
|
|
checkBox.Checked = allAreTrue;
|
|
}
|
|
}
|
|
finally { checkBox.Tag = tag; }
|
|
}
|
|
finally
|
|
{
|
|
changedByUser = true;
|
|
}
|
|
};
|
|
dgv.CellClick += (s, e) => onDataChanged(e);
|
|
dgv.CellContentClick += (s, e) => onDataChanged(e);
|
|
dgv.SelectionChanged += (s, e) => onDataChanged(e);
|
|
if (dgv.DataSource is BindingSource)
|
|
((BindingSource)dgv.DataSource).ListChanged += (s, e) => onDataChanged(e);
|
|
else if (dgv.DataSource is DataSet)
|
|
((DataSet)dgv.DataSource).Tables[dgv.DataMember].ColumnChanged += (s, e) => onDataChanged(e);
|
|
else if (dgv.DataSource is DataTable)
|
|
((DataTable)dgv.DataSource).ColumnChanged += (s, e) => onDataChanged(e);
|
|
|
|
onColResize();
|
|
|
|
return checkBox;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 绘制合并的表头单元格
|
|
/// </summary>
|
|
/// <param name="dgv"></param>
|
|
/// <param name="colNameCollection">单元格名称</param>
|
|
/// <param name="headerText">合并后的表头显示文字</param>
|
|
/// <param name="isEnableResizing">是否允许调整大小</param>
|
|
public static void AddMergeColumnHeader(this DataGridView dgv, List<string> colNameCollection, string headerText, bool isMultiLevelHeader = false)
|
|
{
|
|
int nHeight = 0;
|
|
int nLeft = 0;
|
|
int nTop = 0;
|
|
int nWidth = 0;
|
|
bool isMultiLevel = isMultiLevelHeader; // 是否为二级复合表头
|
|
bool isResize = false; // 是否已调整过表头
|
|
|
|
//合并列中某一列的列宽变化时,强制重绘表头
|
|
dgv.ColumnWidthChanged += (s, e) =>
|
|
{
|
|
if (colNameCollection.Contains(e.Column.Name))
|
|
{
|
|
foreach(var columnName in colNameCollection)
|
|
{
|
|
if (dgv.Columns.Contains(columnName))
|
|
dgv.InvalidateCell(dgv.Columns[columnName].HeaderCell); // 标记单元格为需要重绘
|
|
}
|
|
dgv.Update();
|
|
}
|
|
};
|
|
dgv.Scroll += (s, e) =>
|
|
{
|
|
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
|
|
{
|
|
bool tag = false;
|
|
foreach (var columnName in colNameCollection)
|
|
{
|
|
var bounds = dgv.Columns[columnName].HeaderCell.ContentBounds;
|
|
if (bounds.Left < 10 || bounds.Right > dgv.Width - 10)
|
|
{
|
|
tag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (tag == true)
|
|
{
|
|
foreach (var columnName in colNameCollection)
|
|
{
|
|
if (dgv.Columns.Contains(columnName))
|
|
dgv.InvalidateCell(dgv.Columns[columnName].HeaderCell); // 标记单元格为需要重绘
|
|
}
|
|
dgv.Update();
|
|
}
|
|
}
|
|
};
|
|
//处理重绘事件,绘制合并表头和二级表头
|
|
dgv.CellPainting += (s, e) =>
|
|
{
|
|
if (e.RowIndex == -1 && e.ColumnIndex >=0) // 重绘表头单元格及标题
|
|
{
|
|
string name = dgv.Columns[e.ColumnIndex].Name;
|
|
// 调整为复合表头
|
|
if (isMultiLevel && !isResize)
|
|
{
|
|
dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
|
|
dgv.ColumnHeadersHeight = e.CellBounds.Height * 2;
|
|
isResize = true;
|
|
}
|
|
if (colNameCollection.Contains(name))
|
|
{
|
|
e.PaintBackground(e.CellBounds, false); // false不绘制单元格背景
|
|
//e.PaintContent(e.CellBounds); // 绘制单元格内容,此处不要绘制
|
|
|
|
Brush brush;
|
|
Pen pen;
|
|
if (colNameCollection.IndexOf(name) == 0)
|
|
{
|
|
nTop = e.CellBounds.Top;
|
|
nLeft = e.CellBounds.Left;
|
|
nWidth = e.CellBounds.Width;
|
|
if (isMultiLevelHeader)
|
|
nHeight = e.CellBounds.Height / 2;
|
|
else
|
|
nHeight = e.CellBounds.Height;
|
|
foreach (string str2 in colNameCollection)
|
|
{
|
|
if (!str2.Equals(name))
|
|
{
|
|
nWidth += dgv.Columns[str2].Width;
|
|
}
|
|
}
|
|
}
|
|
//填充表头背景(覆盖原来的分隔线)
|
|
Rectangle rtTmp = new Rectangle(nLeft, nTop, nWidth, nHeight);
|
|
using (brush = new SolidBrush(/*e.CellStyle.BackColor*/dgv.BackgroundColor))
|
|
{
|
|
var rtBounds = e.CellBounds;
|
|
rtBounds.Height -= 1;
|
|
e.Graphics.FillRectangle(brush, rtBounds);
|
|
}
|
|
//非多级表头,只需绘制最后一个连续表头的垂直分隔线
|
|
if (!isMultiLevelHeader)
|
|
{
|
|
if (colNameCollection.IndexOf(name) == colNameCollection.Count - 1)
|
|
{
|
|
// 分隔线
|
|
using (pen = new Pen(Color.FromArgb(229, 229, 229)))
|
|
{
|
|
var rtBounds = e.CellBounds;
|
|
e.Graphics.DrawLine(pen, rtBounds.Right - 1, rtBounds.Top + 1, rtBounds.Right - 1, rtBounds.Bottom - 2);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//分割多级表头
|
|
using (pen = new Pen(/*dgv.GridColor*/Color.FromArgb(229, 229, 229)))
|
|
{
|
|
//水平分隔线
|
|
e.Graphics.DrawLine(pen, nLeft, nHeight, nLeft + nWidth, nHeight);
|
|
//垂直分隔线
|
|
var rtBounds = e.CellBounds;
|
|
if (colNameCollection.IndexOf(name) == colNameCollection.Count - 1)
|
|
e.Graphics.DrawLine(pen, rtBounds.Right - 1, rtBounds.Top + 1, rtBounds.Right - 1, rtBounds.Bottom - 2);
|
|
else
|
|
e.Graphics.DrawLine(pen, rtBounds.Right - 1, nHeight, rtBounds.Right - 1, rtBounds.Bottom - 2);
|
|
}
|
|
//绘制二级表头文字
|
|
using (brush = new SolidBrush(e.CellStyle.ForeColor))
|
|
{
|
|
SizeF textSize = TextRenderer.MeasureText(dgv.Columns[e.ColumnIndex].HeaderText, e.CellStyle.Font);
|
|
int nSubTop = nTop + nHeight;
|
|
int nSubLeft = e.CellBounds.Left;
|
|
int nSubWidth = e.CellBounds.Width;
|
|
int nSubHeight = nHeight;
|
|
PointF point = new PointF(nSubLeft + 6, nSubTop + (nSubHeight - textSize.Height) / 2);
|
|
if (e.CellStyle.Alignment.ToString().Contains("Center"))
|
|
point.X = nSubLeft + (nSubWidth - textSize.Width) / 2;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Right"))
|
|
point.X = nSubLeft + nSubWidth - textSize.Width - 6;
|
|
if (e.CellStyle.Alignment.ToString().Contains("Top"))
|
|
point.Y = nSubTop + 4;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Bottom"))
|
|
point.Y = nSubTop + nSubHeight - textSize.Height - 4;
|
|
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
|
e.Graphics.DrawString(dgv.Columns[e.ColumnIndex].HeaderText, e.CellStyle.Font, brush, point);
|
|
}
|
|
}
|
|
//绘制合并表头名称,只在最后绘制一次
|
|
if (colNameCollection.IndexOf(name) == colNameCollection.Count - 1)
|
|
{
|
|
using (brush = new SolidBrush(e.CellStyle.ForeColor))
|
|
{
|
|
SizeF textSize = TextRenderer.MeasureText(headerText, e.CellStyle.Font);
|
|
//单元列移出可见范围后将不再移动,需要强制改变绘制文字的位置
|
|
if (nLeft < 0)
|
|
nLeft = e.CellBounds.Right - nWidth;
|
|
PointF point = new PointF(nLeft + 6, nTop + (nHeight - textSize.Height) / 2);
|
|
if (e.CellStyle.Alignment.ToString().Contains("Center") || isMultiLevel)
|
|
point.X = nLeft + (nWidth - textSize.Width) / 2;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Right"))
|
|
point.X = nLeft + nWidth - textSize.Width - 6;
|
|
if (e.CellStyle.Alignment.ToString().Contains("Top"))
|
|
point.Y = nTop + 4;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Bottom"))
|
|
point.Y = nTop + nHeight - textSize.Height - 4;
|
|
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
|
e.Graphics.DrawString(headerText, e.CellStyle.Font, brush, point);
|
|
}
|
|
}
|
|
//e.set_Handled(true);
|
|
e.Handled = true; // 告知系统不再处理表头单元格绘制事件
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
public static void AddMergeColumn(this DataGridView dgv, List<string> colNameCollection, Color? VerGridColor = null, Color? VerGridSelectColor = null)
|
|
{
|
|
int nHeight = 0;
|
|
int nLeft = 0;
|
|
int nTop = 0;
|
|
int nWidth = 0;
|
|
|
|
//合并列中某一列的列宽变化时,强制重绘表头
|
|
dgv.ColumnWidthChanged += (s, e) =>
|
|
{
|
|
if (colNameCollection.Contains(e.Column.Name))
|
|
{
|
|
foreach (var columnName in colNameCollection)
|
|
{
|
|
if (dgv.Columns.Contains(columnName))
|
|
dgv.InvalidateCell(dgv.Columns[columnName].HeaderCell); // 标记单元格为需要重绘
|
|
}
|
|
dgv.Update();
|
|
}
|
|
};
|
|
dgv.Scroll += (s, e) =>
|
|
{
|
|
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
|
|
{
|
|
bool tag = false;
|
|
foreach (var columnName in colNameCollection)
|
|
{
|
|
var bounds = dgv.Columns[columnName].HeaderCell.ContentBounds;
|
|
if (bounds.Left < 10 || bounds.Right > dgv.Width - 10)
|
|
{
|
|
tag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (tag == true)
|
|
{
|
|
foreach (var columnName in colNameCollection)
|
|
{
|
|
if (dgv.Columns.Contains(columnName))
|
|
dgv.InvalidateCell(dgv.Columns[columnName].HeaderCell); // 标记单元格为需要重绘
|
|
}
|
|
dgv.Update();
|
|
}
|
|
}
|
|
};
|
|
//处理重绘事件
|
|
dgv.CellPainting += (s, e) =>
|
|
{
|
|
if (e.RowIndex >=0 && e.ColumnIndex >= 0) // 重绘单元格
|
|
{
|
|
string name = dgv.Columns[e.ColumnIndex].Name;
|
|
if (colNameCollection.Contains(name))
|
|
{
|
|
e.PaintBackground(e.CellBounds, true); // false不绘制单元格背景
|
|
e.PaintContent(e.CellBounds); // 绘制单元格内容,此处要绘制内容
|
|
|
|
Brush brush;
|
|
Pen pen;
|
|
if (colNameCollection.IndexOf(name) == 0)
|
|
{
|
|
nTop = e.CellBounds.Top;
|
|
nLeft = e.CellBounds.Left;
|
|
nWidth = e.CellBounds.Width;
|
|
nHeight = e.CellBounds.Height;
|
|
foreach (string str2 in colNameCollection)
|
|
{
|
|
if (!str2.Equals(name))
|
|
{
|
|
nWidth += dgv.Columns[str2].Width;
|
|
}
|
|
}
|
|
}
|
|
//填充背景(覆盖原来的分隔线)
|
|
//Rectangle rtTmp = new Rectangle(nLeft, nTop, nWidth, nHeight);
|
|
//using (brush = new SolidBrush(/*e.CellStyle.BackColor*/dgv.BackgroundColor))
|
|
//{
|
|
// var rtBounds = e.CellBounds;
|
|
// rtBounds.Height -= 1;
|
|
// e.Graphics.FillRectangle(brush, rtBounds);
|
|
//}
|
|
if (colNameCollection.IndexOf(name) < colNameCollection.Count - 1)
|
|
{
|
|
var penColor = VerGridColor;
|
|
// 分隔线
|
|
if (penColor == null)
|
|
{
|
|
//VerGridColor = Color.FromArgb(229, 229, 229);
|
|
penColor = e.RowIndex % 2 == 0 ? dgv.DefaultCellStyle.BackColor : dgv.AlternatingRowsDefaultCellStyle.BackColor;
|
|
}
|
|
var penSelectColor = VerGridSelectColor;
|
|
if (penSelectColor == null)
|
|
//VerGridColorSelect = Color.FromArgb(129, 129, 129);
|
|
penSelectColor = dgv.DefaultCellStyle.SelectionBackColor;
|
|
if ((dgv.Rows[e.RowIndex].Cells[e.ColumnIndex]).Selected)
|
|
{
|
|
using (pen = new Pen(penSelectColor.Value))
|
|
{
|
|
var rtBounds = e.CellBounds;
|
|
e.Graphics.DrawLine(pen, rtBounds.Right - 1, rtBounds.Top, rtBounds.Right - 1, rtBounds.Bottom - 2);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
using (pen = new Pen(penColor.Value))
|
|
{
|
|
var rtBounds = e.CellBounds;
|
|
e.Graphics.DrawLine(pen, rtBounds.Right - 1, rtBounds.Top, rtBounds.Right - 1, rtBounds.Bottom - 2);
|
|
}
|
|
}
|
|
}
|
|
//e.set_Handled(true);
|
|
e.Handled = true; // 告知系统不再处理表头单元格绘制事件
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
public static void AddVerticalMergeCell(this DataGridView dgv, ConcurrentList<DataGridViewCell> cellLst, bool drawRightBorder = true, Color? VerGridColor = null, Color? VerGridSelectColor = null)
|
|
{
|
|
int nHeight = 0;
|
|
int nLeft = 0;
|
|
int nTop = 0;
|
|
int nWidth = 0;
|
|
|
|
dgv.RowHeightChanged += (s, e) =>
|
|
{
|
|
bool has = false;
|
|
foreach (var cell in cellLst)
|
|
{
|
|
if (cell.RowIndex == e.Row.Index)
|
|
{
|
|
dgv.InvalidateCell(cell);
|
|
has = true;
|
|
}
|
|
}
|
|
if (has)
|
|
dgv.Update();
|
|
};
|
|
//合并列中某一列的列宽变化时,强制重绘
|
|
dgv.ColumnWidthChanged += (s, e) =>
|
|
{
|
|
bool has = false;
|
|
foreach (var cell in cellLst)
|
|
{
|
|
if (cell.ColumnIndex == e.Column.Index)
|
|
{
|
|
dgv.InvalidateCell(cell);
|
|
has = true;
|
|
}
|
|
}
|
|
if (has)
|
|
dgv.Update();
|
|
};
|
|
dgv.SelectionChanged += (s, e) =>
|
|
{
|
|
bool has = false;
|
|
foreach (var cell in cellLst)
|
|
{
|
|
if (cell.Displayed)
|
|
{
|
|
dgv.InvalidateCell(cell);
|
|
has = true;
|
|
}
|
|
}
|
|
if (has)
|
|
dgv.Update();
|
|
};
|
|
dgv.Scroll += (s, e) =>
|
|
{
|
|
bool has = false;
|
|
foreach (DataGridViewCell cell in cellLst)
|
|
{
|
|
if (cell.Displayed)
|
|
{
|
|
dgv.InvalidateCell(cell);
|
|
has = true;
|
|
}
|
|
}
|
|
if (has)
|
|
dgv.Update();
|
|
};
|
|
//处理重绘事件
|
|
dgv.CellPainting += (s, e) =>
|
|
{
|
|
if (e.RowIndex >= 0 && e.ColumnIndex >= 0) // 重绘单元格
|
|
{
|
|
foreach(DataGridViewCell cell in cellLst)
|
|
{
|
|
if (cell.RowIndex == e.RowIndex && cell.ColumnIndex == e.ColumnIndex)
|
|
{
|
|
nTop = e.CellBounds.Top;
|
|
nLeft = e.CellBounds.Left;
|
|
nWidth = e.CellBounds.Width;
|
|
nHeight = 0;
|
|
foreach (DataGridViewCell c in cellLst)
|
|
{
|
|
nHeight += dgv.Rows[c.RowIndex].Height;
|
|
}
|
|
for (int i = 0; i < cellLst.IndexOf(cell); i++)
|
|
{
|
|
nTop -= dgv.Rows[cellLst[i].RowIndex].Height;
|
|
}
|
|
var rect = new Rectangle(nLeft, nTop, nWidth - 1, nHeight - 1);
|
|
if (!drawRightBorder)
|
|
rect = new Rectangle(nLeft, nTop, nWidth, nHeight - 1);
|
|
|
|
e.PaintBackground(e.CellBounds, true); // false不绘制单元格背景
|
|
//e.PaintContent(e.CellBounds); // 绘制单元格内容,此处根据需要决定是否绘制内容
|
|
|
|
Brush brush;
|
|
Pen pen;
|
|
//if (cellLst.IndexOf(cell) < cellLst.Count - 1)
|
|
{
|
|
var color = VerGridColor;
|
|
// 分隔线
|
|
if (color == null)
|
|
{
|
|
//VerGridColor = Color.FromArgb(229, 229, 229);
|
|
color = e.RowIndex % 2 == 0 ? dgv.DefaultCellStyle.BackColor : dgv.AlternatingRowsDefaultCellStyle.BackColor;
|
|
color = e.CellStyle.BackColor;
|
|
}
|
|
var selectColor = VerGridSelectColor;
|
|
if (selectColor == null)
|
|
//VerGridColorSelect = Color.FromArgb(129, 129, 129);
|
|
selectColor = dgv.DefaultCellStyle.SelectionBackColor;
|
|
//if ((dgv.Rows[e.RowIndex].Cells[e.ColumnIndex]).Selected)
|
|
if (cellLst.Any(c =>c.Selected))
|
|
{
|
|
//using (pen = new Pen(selectColor.Value))
|
|
//{
|
|
// var rtBounds = e.CellBounds;
|
|
// //e.Graphics.DrawLine(pen, rtBounds.Right - 1, rtBounds.Top, rtBounds.Right - 1, rtBounds.Bottom - 2); // 右竖线
|
|
// e.Graphics.DrawLine(pen, rtBounds.Left, rtBounds.Bottom - 1, rtBounds.Right - 2, rtBounds.Bottom - 1); // 下横线
|
|
//}
|
|
using (brush = new SolidBrush(selectColor.Value))
|
|
{
|
|
e.Graphics.FillRectangle(brush, rect);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//using (pen = new Pen(color.Value))
|
|
//{
|
|
// var rtBounds = e.CellBounds;
|
|
// //e.Graphics.DrawLine(pen, rtBounds.Right - 1, rtBounds.Top, rtBounds.Right - 1, rtBounds.Bottom - 2); // 右竖线
|
|
// e.Graphics.DrawLine(pen, rtBounds.Left, rtBounds.Bottom - 1, rtBounds.Right - 2, rtBounds.Bottom - 1); // 下横线
|
|
//}
|
|
using (brush = new SolidBrush(color.Value))
|
|
{
|
|
e.Graphics.FillRectangle(brush, rect);
|
|
}
|
|
}
|
|
}
|
|
|
|
//if (cellLst.IndexOf(cell) == cellLst.Count - 1)
|
|
if (cell is DataGridViewImageCell == false)
|
|
{
|
|
var color = e.CellStyle.ForeColor;
|
|
if (cellLst.Any(c => c.Selected))
|
|
{
|
|
color = e.CellStyle.SelectionForeColor;
|
|
}
|
|
using (brush = new SolidBrush(color))
|
|
{
|
|
//StringFormat stringFormat = new StringFormat();
|
|
//stringFormat.Alignment = StringAlignment.Near;
|
|
//stringFormat.LineAlignment = StringAlignment.Near;
|
|
//stringFormat.FormatFlags = StringFormatFlags.MeasureTrailingSpaces; // 确保尾部空格被计算在内
|
|
//stringFormat.Trimming = StringTrimming.Character; // 处理超出宽度的字符
|
|
//stringFormat.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, cell.Value.ParseToString().Length) }); // 设置测量范围
|
|
|
|
SizeF textSize = TextRenderer.MeasureText(cell.Value.ParseToString(), e.CellStyle.Font, new Size(nWidth - 10, nHeight), TextFormatFlags.WordBreak);
|
|
//单元列移出可见范围后将不再移动,需要强制改变绘制文字的位置
|
|
if (nLeft < 0)
|
|
nLeft = e.CellBounds.Right - nWidth;
|
|
PointF point = new PointF(nLeft + 1, nTop + (nHeight - textSize.Height) / 2);
|
|
if (e.CellStyle.Alignment.ToString().Contains("Center"))
|
|
point.X = nLeft + (nWidth - textSize.Width) / 2;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Right"))
|
|
point.X = nLeft + nWidth - textSize.Width - 1;
|
|
if (e.CellStyle.Alignment.ToString().Contains("Top"))
|
|
point.Y = nTop + 4;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Bottom"))
|
|
point.Y = nTop + nHeight - textSize.Height - 4;
|
|
e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
|
RectangleF rectF = new RectangleF(point.X, point.Y, nWidth - 10, nHeight - 10);
|
|
//e.Graphics.DrawString(cell.Value.ParseToString(), e.CellStyle.Font, brush, point);
|
|
e.Graphics.DrawString(cell.Value.ParseToString(), e.CellStyle.Font, brush, rectF);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var img = cell.Value as Image;
|
|
|
|
PointF point = new PointF(nLeft, nTop + (nHeight - img.Height) / 2);
|
|
if (e.CellStyle.Alignment.ToString().Contains("Center"))
|
|
point.X = nLeft + (nWidth - img.Width) / 2;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Right"))
|
|
point.X = nLeft + nWidth - img.Width - 1;
|
|
if (e.CellStyle.Alignment.ToString().Contains("Top"))
|
|
point.Y = nTop + 4;
|
|
else if (e.CellStyle.Alignment.ToString().Contains("Bottom"))
|
|
point.Y = nTop + nHeight - img.Height;
|
|
e.Graphics.DrawImage(img, point);
|
|
//RectangleF rectF = new RectangleF(point.X, point.Y, nWidth - 10, nHeight - 10);
|
|
//e.Graphics.DrawString(cell.Value.ParseToString(), e.CellStyle.Font, brush, point);
|
|
//e.Graphics.DrawString(cell.Value.ParseToString(), e.CellStyle.Font, brush, rectF);
|
|
}
|
|
e.Handled = true; // 告知系统不再处理单元格绘制事件
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
public static void AddImgColumn(this DataGridView dgv, string imgColumn, string imgPathColumn, bool isSetHttpsHttp = true)
|
|
{
|
|
dgv.Scroll += (s, e) =>
|
|
{
|
|
ShowDgvImg(dgv, null, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
};
|
|
dgv.Resize += (s, e) =>
|
|
{
|
|
ShowDgvImg(dgv, null, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
};
|
|
dgv.Sorted += (s, e) =>
|
|
{
|
|
ShowDgvImg(dgv, null, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
};
|
|
dgv.RowsRemoved += (s, e) =>
|
|
{
|
|
ShowDgvImg(dgv, null, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
};
|
|
dgv.RowsAdded += (s, e) =>
|
|
{
|
|
ShowDgvImg(dgv, new ConcurrentList<DataGridViewRow> { dgv.Rows[e.RowIndex] }, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
};
|
|
dgv.RowPostPaint += (s, e) =>
|
|
{
|
|
ShowDgvImg(dgv, new ConcurrentList<DataGridViewRow> { dgv.Rows[e.RowIndex] }, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
};
|
|
dgv.CellValueChanged += (s, e) =>
|
|
{
|
|
if (dgv.Columns[e.ColumnIndex].Name == imgPathColumn)
|
|
{
|
|
var row = dgv.Rows[e.RowIndex];
|
|
if (row.Cells[imgColumn].Value != null && row.Cells[imgColumn].Value != defaultBitmap)
|
|
{
|
|
row.Cells[imgColumn].Value = defaultBitmap;
|
|
ShowDgvImg(dgv, new ConcurrentList<DataGridViewRow> { row }, imgColumn, imgPathColumn, isSetHttpsHttp);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
public static Bitmap defaultBitmap = new Bitmap(1,1);
|
|
static void ShowDgvImg(DataGridView dgv, ConcurrentList<DataGridViewRow> rowLst, string imgColumn, string imgPathColumn, bool isSetHttpsHttp = true)
|
|
{
|
|
Task.Run(() =>
|
|
{
|
|
if (rowLst == null)
|
|
{
|
|
rowLst = new ConcurrentList<DataGridViewRow>();
|
|
rowLst.AddRange(dgv.Rows.Cast<DataGridViewRow>());
|
|
}
|
|
foreach (DataGridViewRow row in rowLst)
|
|
{
|
|
if (row.Index > 1 && row.Cells[imgColumn].Displayed == false)
|
|
{
|
|
try
|
|
{
|
|
dgv.Invoke(new Action(() =>
|
|
{
|
|
row.Cells[imgColumn].Value = defaultBitmap;
|
|
}));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (row.Index < 0)
|
|
continue;
|
|
if (row.Index >= 0 && row.Cells[imgColumn].Value != null && row.Cells[imgColumn].Value != defaultBitmap)
|
|
continue;
|
|
|
|
Image image = defaultBitmap;
|
|
if (row.Index >= 0)
|
|
{
|
|
string imgUrl = row.Cells[imgPathColumn]?.Value.ParseToString();
|
|
if (isSetHttpsHttp == true)
|
|
imgUrl = imgUrl.Replace("https://", "http://");
|
|
string getImgError = "";
|
|
if (!string.IsNullOrWhiteSpace(imgUrl))
|
|
{
|
|
image = GetHtml.GetUrlImg(imgUrl, out getImgError);
|
|
if (!string.IsNullOrEmpty(getImgError))
|
|
//BaseMsgForm.ShowError("图片加载失败 " + getImgError);
|
|
image = TemuKJD.Properties.Resources.errpic;
|
|
}
|
|
}
|
|
|
|
try
|
|
{
|
|
dgv.Invoke(new Action(() =>
|
|
{
|
|
if (row.Index >= 0)
|
|
{
|
|
row.Cells[imgColumn].Value = image;
|
|
}
|
|
}));
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
}
|