功能调整
This commit is contained in:
1 parent
42acf1b1cb
commit
772d9f4780
40 files changed
+4953
-389
No files matched your search
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Work.Extension
|
||||
{
|
||||
public static class ControlExtension
|
||||
{
|
||||
public static Point GetRelativePosition(this Control control, Form form)
|
||||
{
|
||||
Point location = control.Location;
|
||||
Control parent = control.Parent;
|
||||
while (parent != null && parent != form)
|
||||
{
|
||||
location.X += parent.Location.X;
|
||||
location.Y += parent.Location.Y;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
public static Point GetRelativePosition(this Control control, Control parentControl)
|
||||
{
|
||||
if (control == null || parentControl == null)
|
||||
return new Point(0, 0);
|
||||
|
||||
Point location = control.Location;
|
||||
Control parent = control.Parent;
|
||||
while (parent != null && parent != parentControl)
|
||||
{
|
||||
location.X += parent.Location.X;
|
||||
location.Y += parent.Location.Y;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
public static Point GetRelativePosition(this Control control)
|
||||
{
|
||||
Point location = control.Location;
|
||||
Control parent = control.Parent;
|
||||
while (parent != null && !(parent is Form))
|
||||
{
|
||||
location.X += parent.Location.X;
|
||||
location.Y += parent.Location.Y;
|
||||
parent = parent.Parent;
|
||||
}
|
||||
return location;
|
||||
}
|
||||
public static Control GetParentNotTable(this Control contorl)
|
||||
{
|
||||
Control parent = contorl.Parent;
|
||||
while (parent != null && (parent is TableLayoutPanel || parent is FlowLayoutPanel))
|
||||
{
|
||||
parent = parent.Parent;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,912 @@
|
||||
using AllBase;
|
||||
using AllBase.Helper;
|
||||
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;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Work.UserComponents;
|
||||
|
||||
namespace Work.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 UcCheckBox 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 UcCheckBox 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, UcCheckBox 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 UcCheckBox();
|
||||
|
||||
checkBox.Name = "chk" + column.Name;
|
||||
}
|
||||
checkBox.Size = new Size(13, 13);
|
||||
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)
|
||||
{
|
||||
//bool isScroll = false;
|
||||
CancellationTokenSource cancelToken = new CancellationTokenSource();
|
||||
|
||||
dgv.Scroll += (s, e) =>
|
||||
{
|
||||
cancelToken.Cancel();
|
||||
cancelToken = new CancellationTokenSource();
|
||||
Task.Run(() =>
|
||||
{
|
||||
//while (isScroll && 1 == 1)
|
||||
// Thread.Sleep(1);
|
||||
//isScroll = true;
|
||||
ShowDgvImg(cancelToken, dgv, dgv.Rows.Cast<DataGridViewRow>().ToList(), imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
//isScroll = false;
|
||||
}, cancelToken.Token);
|
||||
};
|
||||
//dgv.Resize += (s, e) =>
|
||||
//{
|
||||
// ShowDgvImg(dgv, null, imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
//};
|
||||
dgv.Sorted += (s, e) =>
|
||||
{
|
||||
cancelToken.Cancel();
|
||||
cancelToken = new CancellationTokenSource();
|
||||
Task.Run(() =>
|
||||
{
|
||||
//while (isScroll && 1 == 1)
|
||||
// Thread.Sleep(1);
|
||||
//isScroll = true;
|
||||
ShowDgvImg(cancelToken, dgv, dgv.Rows.Cast<DataGridViewRow>().ToList(), imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
//isScroll = false;
|
||||
}, cancelToken.Token);
|
||||
};
|
||||
//dgv.RowsRemoved += (s, e) =>
|
||||
//{
|
||||
// ShowDgvImg(dgv, null, imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
//};
|
||||
dgv.RowsAdded += (s, e) =>
|
||||
{
|
||||
cancelToken.Cancel();
|
||||
cancelToken = new CancellationTokenSource();
|
||||
Task.Run(() =>
|
||||
{
|
||||
//while (isScroll && 1 == 1)
|
||||
// Thread.Sleep(1);
|
||||
//isScroll = true;
|
||||
if (e.RowIndex < (dgv.FirstDisplayedScrollingRowIndex + dgv.DisplayedRowCount(true)))
|
||||
ShowDgvImg(cancelToken, dgv, dgv.Rows.Cast<DataGridViewRow>().ToList(), imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
else
|
||||
ShowDgvImg(cancelToken, dgv, new List<DataGridViewRow> { dgv.Rows[e.RowIndex] }, imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
//isScroll = false;
|
||||
}, cancelToken.Token);
|
||||
};
|
||||
dgv.RowPostPaint += (s, e) =>
|
||||
{
|
||||
//if (e.RowIndex >= 0 && e.RowIndex < 25)
|
||||
//{
|
||||
// Task.Run(() =>
|
||||
// {
|
||||
// while (isScroll && 1 == 1)
|
||||
// Thread.Sleep(1);
|
||||
// isScroll = true;
|
||||
// try
|
||||
// {
|
||||
// if (dgv.Rows.Count > e.RowIndex)
|
||||
// ShowDgvImg(dgv, new List<DataGridViewRow> { dgv.Rows[e.RowIndex] }, imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
|
||||
// }
|
||||
// isScroll = false;
|
||||
// });
|
||||
//}
|
||||
};
|
||||
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;
|
||||
|
||||
cancelToken.Cancel();
|
||||
cancelToken = new CancellationTokenSource();
|
||||
Task.Run(() =>
|
||||
{
|
||||
//while (isScroll && 1 == 1)
|
||||
// Thread.Sleep(1);
|
||||
//isScroll = true;
|
||||
ShowDgvImg(cancelToken, dgv, new List<DataGridViewRow> { row }, imgColumn, imgPathColumn, isSetHttpsHttp);
|
||||
//isScroll = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Bitmap defaultBitmap = new Bitmap(1, 1);
|
||||
static void ShowDgvImg(CancellationTokenSource cancelToken, DataGridView dgv, List<DataGridViewRow> rowLst, string imgColumn, string imgPathColumn, bool isSetHttpsHttp = true)
|
||||
{
|
||||
if (rowLst == null)
|
||||
{
|
||||
rowLst = new List<DataGridViewRow>();
|
||||
rowLst.AddRange(dgv.Rows.Cast<DataGridViewRow>());
|
||||
}
|
||||
foreach (DataGridViewRow row in rowLst)
|
||||
{
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
//if (row.Index <= 1)
|
||||
// continue;
|
||||
if (row.Displayed == false && row.Index > 0) // 不设置大于0 第一行始终不显示图片
|
||||
{
|
||||
dgv.Invoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (row.Index >= 0 && row.Cells[imgColumn]?.Value != defaultBitmap)
|
||||
row.Cells[imgColumn].Value = defaultBitmap;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
if (row.Cells[imgColumn]?.Value == defaultBitmap || row.Cells[imgColumn]?.Value == null)
|
||||
{
|
||||
Image image = defaultBitmap;
|
||||
string imgUrl = row.Cells[imgPathColumn]?.Value.ParseToString();
|
||||
if (!string.IsNullOrWhiteSpace(imgUrl))
|
||||
{
|
||||
if (isSetHttpsHttp == true)
|
||||
imgUrl = imgUrl.Replace("https://", "http://");
|
||||
string getImgError = "";
|
||||
image = GetHtml.GetUrlImg(imgUrl, out getImgError);
|
||||
if (!string.IsNullOrEmpty(getImgError))
|
||||
//BaseMsgForm.ShowError("图片加载失败 " + getImgError);
|
||||
image = Properties.Resources.errpic;
|
||||
}
|
||||
|
||||
dgv.Invoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (row.Index >= 0)
|
||||
{
|
||||
row.Cells[imgColumn].Value = image;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user