using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Reflection; using System.Runtime; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; namespace DPumpHydr.WinFrmUI.WenSkin.Controls { [ToolboxBitmap(typeof(DataGridView))] public class WenDataGridView : DataGridView { public event DataGridViewCellMouseEventHandler TextBoxButtonClick; public WenDataGridView() { base.SetStyle( ControlStyles.UserPaint | ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor, true); base.UpdateStyles(); this.BackgroundColor = Color.FromArgb(37, 37, 38); this.ColumnHeadersHeight = 30; this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing; //修改为默认选择整行 this.SelectionMode = DataGridViewSelectionMode.FullRowSelect; this.EnableHeadersVisualStyles = false; this.DefaultCellStyle = new DataGridViewCellStyle(this.DefaultCellStyle) { BackColor = Color.FromArgb(37, 37, 38), SelectionBackColor = Color.FromArgb(63, 63, 70) }; this.RowHeadersDefaultCellStyle = new DataGridViewCellStyle(this.RowHeadersDefaultCellStyle) { BackColor = Color.FromArgb(37, 37, 38), SelectionBackColor = Color.FromArgb(63, 63, 70), ForeColor = Color.White, }; this.ColumnHeadersDefaultCellStyle = new DataGridViewCellStyle(this.RowHeadersDefaultCellStyle) { BackColor = Color.FromArgb(37, 37, 38), SelectionBackColor = Color.FromArgb(63, 63, 70), ForeColor = Color.White, }; } #region 私有属性 private TreeDataSourceNode treeDataSourceNode; private CheckBoxStateCollection checkedBoxs; private TreeDataGridViewRowNodeCollection nodes; private bool radioButtones; private bool checkBoxes; private int radioButtonRowIndex = -1; private StringFormat StringConters { get; set; } = new StringFormat(StringFormatFlags.NoClip | StringFormatFlags.NoWrap) { LineAlignment = StringAlignment.Center, Alignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter }; #endregion #region 公有属性 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] [Category("Wen")] [Description("绑定数据节点信息设置")] public TreeDataSourceNode TreeDataSourceNode => treeDataSourceNode ??= new TreeDataSourceNode(); [DefaultValue(10), Category("Wen"), Description("折叠按钮缩进值")] public int Indent { get; set; } = 10; [DefaultValue(false), Category("Wen"), Description("右键是否弹出筛选菜单")] public bool MouseButtonsRightFilterMenu { get; set; } [DefaultValue(false), Category("Wen"), Description("是否增加复选框")] public bool CheckBoxes { get => checkBoxes; set { checkBoxes = value; if (value) RadioButtones = false; } } [DefaultValue(false), Category("Wen"), Description("是否增加单选框")] public bool RadioButtones { get => radioButtones; set { radioButtones = value; if (value) CheckBoxes = false; } } [DefaultValue(null), Category("Wen"), Description("复选框集合")] [Browsable(false)] public CheckBoxStateCollection CheckedBoxs => checkedBoxs ??= new CheckBoxStateCollection(this); [DefaultValue(null), Category("Wen"), Description("单选框选择行")] [Browsable(false)] public int RadioButtonRowIndex { get => radioButtonRowIndex; } [DefaultValue(null), Category("Wen"), Description("节点数据")] [Browsable(false)] public TreeDataGridViewRowNodeCollection Nodes => nodes ??= new TreeDataGridViewRowNodeCollection(); [DefaultValue(DataGridViewSelectionMode.FullRowSelect)] public new DataGridViewSelectionMode SelectionMode { get => base.SelectionMode; set => base.SelectionMode = value; } #endregion #region 委托 public event DataGridViewRowCheckBoxEventHandler DataGridViewRowCheckBoxClick; public delegate void DataGridViewRowCheckBoxEventHandler(object sender, DataGridViewRowCheckBoxEventArgs e); public class DataGridViewRowCheckBoxEventArgs : EventArgs { private readonly int rowIndex; private readonly bool state; public DataGridViewRowCheckBoxEventArgs(int rowIndex, bool state) { this.rowIndex = rowIndex; this.state = state; } public int RowIndex => rowIndex; public bool State => state; } public virtual void OnTextBoxButtonClick(DataGridViewCellMouseEventArgs e) { TextBoxButtonClick?.Invoke(this, e); } //筛选委托 public event WenDataGridViewFilterControl.WenDataGridViewFilterEventHandler WenDataGridViewFilter; public class DataGridViewRowItemClickEventArgs : EventArgs { public DataGridViewRowItemClickEventArgs(DataGridView dataGridView, DataGridViewCellMouseEventArgs e) { DataGridView = dataGridView; this.e = e; this.RowIndex = e.RowIndex; this.ColumnIndex = e.ColumnIndex; var data = dataGridView.Rows[RowIndex].DataBoundItem; DataGridViewRow = dataGridView.Rows[RowIndex]; DataRow = data.GetType().GetProperty("Row").GetValue(data, null) as DataRow; } public DataGridViewRow DataGridViewRow { get; private set; } public DataRow DataRow { get; private set; } public int RowIndex { get; private set; } public int ColumnIndex { get; private set; } public DataGridView DataGridView { get; private set; } public DataGridViewCellMouseEventArgs e { get; private set; } } public delegate void DataGridViewRowItemClickEventHandler(object sender, DataGridViewRowItemClickEventArgs e); public event DataGridViewRowItemClickEventHandler RowItemClick; #endregion #region 重绘 //重绘外边框 protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); Graphics g = e.Graphics; g.SetGDIHigh(); using Pen p = new Pen(Color.FromArgb(160, 160, 160)); g.DrawRectangle(p, new Rectangle(0, 0, this.Width - 1, this.Height - 1)); } //重绘每个单元格内容 protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e) { //base.OnCellPainting(e); Graphics g = e.Graphics.SetGDIHigh(); Rectangle rec = e.CellBounds; using Brush bBack = new SolidBrush(e.CellStyle.BackColor); using Pen pen = new Pen(Color.FromArgb(160, 160, 160)); //第一行第一列 if (e.RowIndex == -1 && e.ColumnIndex == -1) { DrawBack(bBack, rec); string str = "序号"; if (CheckBoxes || RadioButtones) str = "选择"; g.DrawString(str, e.CellStyle.Font, new SolidBrush(e.CellStyle.ForeColor), rec, StringConters); } //标题行 else if (e.RowIndex == -1) { DrawBack(bBack, rec); DrawTitleRow(); } //标题栏 else if (e.ColumnIndex == -1) { if ((e.State & DataGridViewElementStates.Selected) != 0) { DrawBack(new SolidBrush(Color.FromArgb(63, 63, 70)), rec); } else { DrawBack(new SolidBrush(Color.FromArgb(37, 37, 38)), rec); } Rectangle recStr = rec; //增加复选框 if (CheckBoxes || RadioButtones) { int checkWidth = 15; int checkY = (rec.Height - checkWidth) / 2 + rec.Y; if (CheckBoxes) { if (CheckedBoxs[e.RowIndex].State) { CheckBoxRenderer.DrawCheckBox(g, new Point(rec.X, checkY), System.Windows.Forms.VisualStyles.CheckBoxState.CheckedNormal); } else { CheckBoxRenderer.DrawCheckBox(g, new Point(rec.X, checkY), System.Windows.Forms.VisualStyles.CheckBoxState.UncheckedNormal); } } if (RadioButtones) { //当前激活行 if (e.RowIndex == radioButtonRowIndex && this.CurrentCell.RowIndex == e.RowIndex) { RadioButtonRenderer.DrawRadioButton(g, new Point(rec.X, checkY), System.Windows.Forms.VisualStyles.RadioButtonState.CheckedNormal); } else { RadioButtonRenderer.DrawRadioButton(g, new Point(rec.X, checkY), System.Windows.Forms.VisualStyles.RadioButtonState.UncheckedNormal); } } recStr = new Rectangle(rec.X + 17, rec.Y, rec.Width - 17 - rec.X, rec.Height); } //画序号 g.DrawString((e.RowIndex + 1).ToString(), e.CellStyle.Font, new SolidBrush(e.CellStyle.ForeColor), recStr, WenSkin.Controls.ControlHelper.StringConters); } //画背景 void DrawBack(Brush brush, Rectangle rec) { g.FillRectangle(brush, rec); //底部线条 g.DrawLine(pen, rec.X, rec.Y + rec.Height - 1, rec.X + rec.Width - 1, rec.Y + rec.Height - 1); //单元格边上线条 g.DrawLine(pen, rec.X + rec.Width - 1, rec.Y, rec.X + rec.Width - 1, rec.Y + rec.Height - 1); e.Handled = true; brush.Dispose(); } void DrawTitleRow() { //画单元格内容 Rectangle recString = new Rectangle(rec.X, rec.Y, rec.Width, rec.Height); Rectangle recImage = new Rectangle(rec.X + (rec.Width - 16), rec.Y + (rec.Height - 12) / 2, 12, 12); //文字水平垂直居中 g.DrawString(e.Value?.ToString(), e.CellStyle.Font, new SolidBrush(ForeColor), recString, StringConters); if (FilterColumns.ContainsKey(this.Columns[e.ColumnIndex])) { g.FillRectangle(new SolidBrush(this.BackgroundColor), new Rectangle(rec.X + (rec.Width - 18), rec.Y + (rec.Height - 16) / 2, 16, 16)); g.DrawImage(Properties.Resources.筛选, recImage); } else if (e.ColumnIndex == MouserMoveColumnIndex) { g.FillRectangle(new SolidBrush(this.BackgroundColor), new Rectangle(rec.X + (rec.Width - 18), rec.Y + (rec.Height - 16) / 2, 16, 16)); g.DrawImage(Properties.Resources.三角形下, recImage); } } } #endregion #region 复选框问题处理 public class CheckBoxState { private bool state; public WenDataGridView DataGridView { get; private set; } public CheckBoxState(int rowIndex, bool state, WenDataGridView wenDataGridView) { RowIndex = rowIndex; State = state; this.DataGridView = wenDataGridView; } public int RowIndex { get; set; } public bool State { get => state; set { state = value; } } } public class CheckBoxStateCollection : List { private readonly WenDataGridView owner; public CheckBoxStateCollection(WenDataGridView owner) { this.owner = owner; } public WenDataGridView DataGridView => owner; public new CheckBoxState this[int index] { get { if (Find(a => a.RowIndex == index) is CheckBoxState check) { return check; } else { CheckBoxState checkBoxState = new CheckBoxState(index, false, this.owner); Add(checkBoxState); return checkBoxState; } } } } #endregion #region 鼠标点击事件 protected override void OnCellMouseClick(DataGridViewCellMouseEventArgs e) { base.OnCellMouseClick(e); if (e.RowIndex == -1 && e.ColumnIndex > -1 && MouseButtonsRightFilterMenu) { Rectangle rec = this.GetCellDisplayRectangle(e.ColumnIndex, e.RowIndex, true); Rectangle recImage = new Rectangle(0 + (rec.Width - 18), 0 + (rec.Height - 16) / 2, 16, 16); if (recImage.Contains(e.Location) || e.Button == MouseButtons.Right) { var fm = new WenDataGridViewFilterControl(this, this.Columns[e.ColumnIndex]); fm.WenDataGridViewFilter += (s, e) => { WenDataGridViewFilter?.Invoke(this, e); }; fm.ShowDialog(); } } if (e.RowIndex > -1) { radioButtonRowIndex = e.RowIndex; if (CheckedBoxs[e.RowIndex].State) { CheckedBoxs[e.RowIndex].State = false; } else { CheckedBoxs[e.RowIndex].State = true; } this.InvalidateRow(e.RowIndex); DataGridViewRowCheckBoxClick?.Invoke(this, new DataGridViewRowCheckBoxEventArgs(e.RowIndex, CheckedBoxs[e.RowIndex].State)); RowItemClick?.Invoke(this, new DataGridViewRowItemClickEventArgs(this, e)); } } #endregion #region 鼠标移动事件 private int MouserMoveColumnIndex = -1; protected override void OnCellMouseMove(DataGridViewCellMouseEventArgs e) { base.OnCellMouseMove(e); if (e.RowIndex == -1) { if (MouserMoveColumnIndex == e.ColumnIndex) return; this.Invalidate(this.GetCellDisplayRectangle(MouserMoveColumnIndex, -1, true)); this.Invalidate(this.GetCellDisplayRectangle(e.ColumnIndex, -1, true)); MouserMoveColumnIndex = e.ColumnIndex; } } protected override void OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); this.Invalidate(this.GetCellDisplayRectangle(MouserMoveColumnIndex, -1, true)); MouserMoveColumnIndex = -1; } #endregion #region 筛选列数据记录 public Dictionary> FilterColumns = new Dictionary>(); //排序改变前后处理 public void FilterWenDataGridViewRow() { //首先全部显示 foreach (DataGridViewRow row in this.Rows) { row.Visible = true; } foreach (var item in FilterColumns) { foreach (DataGridViewRow row in this.Rows) { if (row.IsNewRow || !row.Visible) continue; if (item.Value.Contains(row.Cells[item.Key.Index].Value?.ToString())) { row.Visible = false; } } } } #endregion #region 排序改变事件 protected override void OnSorted(EventArgs e) { base.OnSorted(e); FilterWenDataGridViewRow(); CheckedBoxs.Clear(); radioButtonRowIndex = -1; } #endregion #region 绑定数据 private object dataSource { get; set; } public new object DataSource { get => dataSource; set { this.CheckedBoxs.Clear(); radioButtonRowIndex = -1; this.FilterColumns.Clear(); dataSource = value; if (TreeDataSourceNode.TreeDataSource) { DataBind(value); } else { base.DataSource = value; //不允许排序功能 foreach (DataGridViewColumn item in base.Columns) { item.SortMode = DataGridViewColumnSortMode.NotSortable; } } } } private void DataBind(object value) { if (value == null) return; //tree模式不允许排序功能 foreach (DataGridViewColumn item in base.Columns) { item.SortMode = DataGridViewColumnSortMode.NotSortable; } if (value is DataSet ds) { DataBind(ds.Tables[0]); } else if (value is DataTable dt) { DataBind(dt); } void DataBind(DataTable dt) { this.Nodes.Clear(); this.Rows.Clear(); //判定是否是数据绑定输结构模式 DataBindTreeNode(dt, this.Nodes, null, TreeDataSourceNode.RootContent, 0, Indent, ""); } } #endregion #region 绑定节点 private TreeDataGridViewRowNodeCollection DataBindTreeNode(DataTable dt, TreeDataGridViewRowNodeCollection nodes, DataGridViewRow parentLevel , string value, int level, int indent, string paternelnodePath) { DataRow[] rows = dt.Select($"{TreeDataSourceNode.ParentNode}=\'{value}\'"); int index = 0; foreach (var item in rows) { int indexRow = this.Rows.Add(); DataGridViewRow dataGridViewRow = Rows[indexRow]; TreeDataGridViewCellValues treeData = new TreeDataGridViewCellValues(); string nodePath = paternelnodePath + "/" + index++; TreeDataGridViewRowNode node = new TreeDataGridViewRowNode(this) { ParentLevel = parentLevel, DataGridViewRow = dataGridViewRow, }; string parentValue = string.Empty; if (item is DataRow row) { parentValue = row[TreeDataSourceNode.ChildNode]?.ToString(); foreach (DataGridViewColumn column in base.Columns) { DataGridViewCell cell = column.CellTemplate; if (cell is WenTreeDataGridViewTextBoxCell) { treeData = new TreeDataGridViewCellValues() { Text = row[column.DataPropertyName]?.ToString(), Level = level, Indent = indent, NodePath = nodePath, }; dataGridViewRow.Cells[column.Name].Value = treeData; } else { dataGridViewRow.Cells[column.Name].Value = row.Table.Columns.Contains(column.DataPropertyName) ? row[column.DataPropertyName] : null; } } } nodes.Add(node); var subnodes = DataBindTreeNode(dt, node.Nodes, dataGridViewRow, parentValue, level + 1, indent, nodePath); treeData.Nodes.AddRange(subnodes); treeData.TreeDataGridViewRowNode = node; node.Nodes.AddRange(subnodes); } return nodes; } #endregion } }