Files
KJD/TEMUKJD/Extension/DataGridViewExtension.cs
T

241 lines
9.9 KiB
C#

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(15, 15);
checkBox.BackColor = Color.Transparent;
checkBox.Enabled = true;
// Reset properties
checkBox.Padding = new Padding(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>());
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;
}
}
}