// ***********************************************************************
// Assembly : JinYuan.ControlLib
// Created : 08-09-2019
//
// ***********************************************************************
//
// Copyright by Huang Zhenghui(黄正辉) All, QQ group:568015492 QQ:623128629 Email:623128629@qq.com
//
//
// Blog: https://www.cnblogs.com/bfyx
// GitHub:https://github.com/kwwwvagaa/NetWinformControl
// gitee:https://gitee.com/kwwwvagaa/net_winform_custom_control.git
//
// If you use this code, please keep this note.
// ***********************************************************************
using JinYuan.ControlLib.UCHelper;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace JinYuan.ControlLib
{
///
/// Class UCDataGridView.
/// Implements the
///
///
public partial class UCDataGridView : UserControl
{
#region 属性
///
/// The m head pading left
///
private int m_headPadingLeft = 0;
///
/// Gets or sets the head pading left.
///
/// The head pading left.
[Description("标题左侧间距"), Category("自定义")]
public int HeadPadingLeft
{
get { return m_headPadingLeft; }
set
{
m_headPadingLeft = value;
this.panHeadLeft.Width = m_headPadingLeft;
}
}
///
/// The m head font
///
private Font m_headFont = new Font("微软雅黑", 12F);
///
/// 标题字体
///
/// The head font.
[Description("标题字体"), Category("自定义")]
public Font HeadFont
{
get { return m_headFont; }
set { m_headFont = value; }
}
///
/// The m head text color
///
private Color m_headTextColor = Color.Black;
///
/// 标题字体颜色
///
/// The color of the head text.
[Description("标题文字颜色"), Category("自定义")]
public Color HeadTextColor
{
get { return m_headTextColor; }
set { m_headTextColor = value; }
}
///
/// The m is show head
///
private bool m_isShowHead = true;
///
/// 是否显示标题
///
/// true if this instance is show head; otherwise, false.
[Description("是否显示标题"), Category("自定义")]
public bool IsShowHead
{
get { return m_isShowHead; }
set
{
if (m_isShowHead != value)
{
m_isShowHead = value;
panHead.Visible = value;
if (value)
{
this.panRow.Location = new Point(0, panHead.Height);
this.panRow.Height = this.panRow.Height - panHead.Height;
}
else
{
this.panRow.Location = new Point(0, 0);
this.panRow.Height = this.panRow.Height + panHead.Height;
}
}
}
}
///
/// The m head height
///
private int m_headHeight = 40;
///
/// 标题高度
///
/// The height of the head.
[Description("标题高度"), Category("自定义")]
public int HeadHeight
{
get { return m_headHeight; }
set
{
m_headHeight = value;
panHead.Height = value;
this.Padding = new Padding(0, value, 0, 0);
}
}
///
/// The m is show CheckBox
///
private bool m_isShowCheckBox = false;
///
/// 是否显示复选框
///
/// true if this instance is show CheckBox; otherwise, false.
[Description("是否显示选择框"), Category("自定义")]
public bool IsShowCheckBox
{
get { return m_isShowCheckBox; }
set
{
if (value != m_isShowCheckBox)
{
m_isShowCheckBox = value;
LoadColumns();
}
}
}
///
/// The m row height
///
private int m_rowHeight = 40;
///
/// 行高
///
/// The height of the row.
[Description("数据行高"), Category("自定义")]
public int RowHeight
{
get { return m_rowHeight; }
set { m_rowHeight = value; }
}
///
/// Gets the show count.
///
/// The show count.
[Description("当前高度可显示行个数"), Category("自定义")]
public int ShowCount
{
get
{
return this.panRow.Height / (m_rowHeight);
}
}
///
/// The m columns
///
private List m_columns = null;
///
/// 列
///
/// The columns.
[Description("列"), Category("自定义")]
public List Columns
{
get { return m_columns; }
set
{
m_columns = value;
LoadColumns();
}
}
///
/// The m data source
///
private object m_dataSource = null;
///
/// 数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的DataSource
///
/// The data source.
/// 数据源不是有效的数据类型,请使用Datatable或列表
/// 数据源不是有效的数据类型,请使用Datatable或列表
[Description("数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的DataSource"), Category("自定义")]
public object DataSource
{
get { return m_dataSource; }
set
{
if (value != null)
{
if (!(value is DataTable) && (!typeof(IList).IsAssignableFrom(value.GetType())))
{
throw new Exception("数据源不是有效的数据类型,请使用Datatable或列表");
}
}
m_dataSource = value;
if (m_columns != null && m_columns.Count > 0)
{
ReloadSource();
}
if (BindingSourceEvent != null)
{
BindingSourceEvent(this, null);
}
}
}
///
/// Gets the rows.
///
/// The rows.
public List Rows { get; private set; }
///
/// The m row type
///
private Type m_rowType = typeof(UCDataGridViewRow);
///
/// 行元素类型,默认UCDataGridViewItem
///
/// The type of the row.
/// 行控件没有实现IDataGridViewRow接口
/// 行控件没有实现IDataGridViewRow接口
[Description("行控件类型,默认UCDataGridViewRow,如果不满足请自定义行控件实现接口IDataGridViewRow"), Category("自定义")]
public Type RowType
{
get { return m_rowType; }
set
{
if (value == null)
return;
if (!typeof(IDataGridViewRow).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
throw new Exception("行控件没有实现IDataGridViewRow接口");
m_rowType = value;
if (m_columns != null && m_columns.Count > 0)
ReloadSource();
}
}
///
/// The m select row
///
IDataGridViewRow m_selectRow = null;
///
/// 选中的节点
///
/// The select row.
[Description("选中行"), Category("自定义")]
public IDataGridViewRow SelectRow
{
get { return m_selectRow; }
private set { m_selectRow = value; }
}
///
/// 选中的行,如果显示CheckBox,则以CheckBox选中为准
///
/// The select rows.
[Description("选中的行,如果显示CheckBox,则以CheckBox选中为准"), Category("自定义")]
public List SelectRows
{
get
{
return GetSelectRows();
}
}
///
/// Gets the select rows.
///
/// List<IDataGridViewRow>.
private List GetSelectRows()
{
List lst = new List();
if (m_isShowCheckBox)
{
if (Rows != null && Rows.Count > 0)
lst.AddRange(Rows.FindAll(p => p.IsChecked));
}
else
{
if (m_selectRow != null)
lst.AddRange(new List() { m_selectRow });
}
if (Rows != null && Rows.Count > 0 && m_rowType == typeof(UCDataGridViewTreeRow))
{
foreach (UCDataGridViewTreeRow row in Rows)
{
lst.AddRange(FindTreeRowSelected(row));
}
}
return lst;
}
private List FindTreeRowSelected(UCDataGridViewTreeRow row)
{
List lst = new List();
var _lst = row.ChildrenRows.FindAll(p => p.IsChecked);
lst.AddRange(_lst);
foreach (UCDataGridViewTreeRow _row in row.ChildrenRows)
{
lst.AddRange(FindTreeRowSelected(_row));
}
return lst;
}
///
/// Finds the child grid.
///
/// The c.
/// UCDataGridView.
private UCDataGridView FindChildGrid(Control c)
{
foreach (Control item in c.Controls)
{
if (item is UCDataGridView)
return item as UCDataGridView;
else if (item.Controls.Count > 0)
{
var grid = FindChildGrid(item);
if (grid != null)
return grid;
}
}
return null;
}
[Bindable(false)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool AutoScroll
{
get
{
return base.AutoScroll;
}
set
{
base.AutoScroll = value;
}
}
#region 事件
///
/// The head CheckBox change event
///
[Description("选中标题选择框事件"), Category("自定义")]
public EventHandler HeadCheckBoxChangeEvent;
///
/// The head column click event
///
[Description("标题点击事件"), Category("自定义")]
public EventHandler HeadColumnClickEvent;
///
/// Occurs when [item click].
///
[Description("项点击事件"), Category("自定义")]
public event DataGridViewEventHandler ItemClick;
///
/// Occurs when [source changed].
///
[Description("行数据源改变事件"), Category("自定义")]
public event DataGridViewEventHandler RowSourceChangedEvent;
///
/// Occurs when [row custom event].
///
[Description("预留的自定义的事件,比如你需要在行上放置删改等按钮时,可以通过此事件传递出来"), Category("自定义")]
public event DataGridViewRowCustomEventHandler RowCustomEvent;
[Description("绑定数据源后事件"), Category("自定义")]
public event EventHandler BindingSourceEvent;
#endregion
#endregion
///
/// Initializes a new instance of the class.
///
public UCDataGridView()
{
InitializeComponent();
}
#region 私有方法
#region 加载column
///
/// 功能描述:加载column
/// 作 者:HZH
/// 创建日期:2019-08-08 17:51:50
/// 任务编号:POS
///
private void LoadColumns()
{
try
{
if (DesignMode)
{ return; }
ControlHelper.FreezeControl(this.panHead, true);
this.panRow.Controls.Clear();
this.panColumns.Controls.Clear();
this.panColumns.ColumnStyles.Clear();
if (m_columns != null && m_columns.Count() > 0)
{
int _width = 0;
m_columns.ForEach(p =>
{
if (p.WidthType == SizeType.Absolute)
{
_width += p.Width;
}
else if (p.WidthType == SizeType.Percent)
{
_width += (int)((p.Width / 100f) * this.Width);
}
});
if (m_isShowCheckBox)
_width += 30;
if (_width > this.Width)
{
//this.panRow.Width = _width;
this.panHead.Width = _width;
}
else
{
if (m_columns.Any(p => p.WidthType == SizeType.AutoSize))
{
//this.panRow.Width = this.Width;
this.panHead.Width = this.Width;
}
else
{
//this.panRow.Width = _width;
this.panHead.Width = _width;
}
}
m_columns.FindAll(p => p.WidthType == SizeType.Absolute);
m_columns.FindAll(p => p.WidthType == SizeType.Percent);
int intColumnsCount = m_columns.Count();
if (m_isShowCheckBox)
{
intColumnsCount++;
}
this.panColumns.ColumnCount = intColumnsCount;
for (int i = 0; i < intColumnsCount; i++)
{
Control c = null;
if (i == 0 && m_isShowCheckBox)
{
this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F));
UCCheckBox box = new UCCheckBox();
box.TextValue = "";
box.Size = new Size(30, 30);
box.CheckedChangeEvent += (a, b) =>
{
Rows.ForEach(p => p.IsChecked = box.Checked);
if (HeadCheckBoxChangeEvent != null)
{
HeadCheckBoxChangeEvent(a, b);
}
};
c = box;
}
else
{
var item = m_columns[i - (m_isShowCheckBox ? 1 : 0)];
this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width));
Label lbl = new Label();
lbl.Name = "dgvColumns_" + i;
lbl.Text = item.HeadText;
lbl.Font = m_headFont;
lbl.ForeColor = m_headTextColor;
lbl.TextAlign = ContentAlignment.MiddleCenter;
lbl.AutoSize = false;
lbl.Dock = DockStyle.Fill;
lbl.MouseDown += (a, b) =>
{
if (HeadColumnClickEvent != null)
{
HeadColumnClickEvent(a, b);
}
};
c = lbl;
}
this.panColumns.Controls.Add(c, i, 0);
}
}
}
finally
{
ControlHelper.FreezeControl(this.panHead, false);
}
}
#endregion
#endregion
#region 公共函数
///
/// 刷新数据
///
public void ReloadSource()
{
if (DesignMode)
{ return; }
try
{
ControlHelper.FreezeControl(this, true);
panHead.Location = new Point(0, 0);
Rows = new List();
if (m_columns == null || m_columns.Count <= 0)
return;
if (m_dataSource != null)
{
int intIndex = 0;
int intSourceCount = 0;
if (m_dataSource is DataTable)
{
intSourceCount = (m_dataSource as DataTable).Rows.Count;
}
else if (typeof(IList).IsAssignableFrom(m_dataSource.GetType()))
{
intSourceCount = (m_dataSource as IList).Count;
}
foreach (Control item in this.panRow.Controls)
{
if (intIndex >= intSourceCount)
{
item.Visible = false;
}
else
{
var row = (item as IDataGridViewRow);
row.IsShowCheckBox = m_isShowCheckBox;
if (m_dataSource is DataTable)
{
row.DataSource = (m_dataSource as DataTable).Rows[intIndex];
}
else
{
row.DataSource = (m_dataSource as IList)[intIndex];
}
row.BindingCellData();
if (row.RowHeight != m_rowHeight)
row.RowHeight = m_rowHeight;
item.Visible = true;
item.Width = panHead.Width;
Rows.Add(row);
row.RowIndex = Rows.IndexOf(row);
}
intIndex++;
}
if (intIndex < intSourceCount)
{
for (int i = intIndex; i < intSourceCount; i++)
{
IDataGridViewRow row = (IDataGridViewRow)Activator.CreateInstance(m_rowType);
if (m_dataSource is DataTable)
{
row.DataSource = (m_dataSource as DataTable).Rows[i];
}
else
{
row.DataSource = (m_dataSource as IList)[i];
}
row.Columns = m_columns;
List lstCells = new List();
row.IsShowCheckBox = m_isShowCheckBox;
row.ReloadCells();
row.BindingCellData();
Control rowControl = (row as Control);
rowControl.Width = panHead.Width;
row.RowHeight = m_rowHeight;
row.CellClick += (a, b) => { this.FindForm().ActiveControl = this; rowControl.Focus(); SetSelectRow(rowControl, b); };
row.CheckBoxChangeEvent += (a, b) => { SetSelectRow(rowControl, b); };
row.RowCustomEvent += (a, b) => { if (RowCustomEvent != null) { RowCustomEvent(a, b); } };
row.SourceChanged += RowSourceChanged;
Rows.Add(row);
row.RowIndex = Rows.IndexOf(row);
this.panRow.Controls.Add(rowControl);
}
}
//this.panRow.Height = intSourceCount * RowHeight;
}
else
{
foreach (Control item in this.panRow.Controls)
{
item.Visible = false;
}
}
}
finally
{
ControlHelper.FreezeControl(this, false);
}
}
///
/// 快捷键
///
/// 通过引用传递的 ,它表示要处理的窗口消息。
/// 值之一,它表示要处理的键。
/// 如果字符已由控件处理,则为 true;否则为 false。
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Up)
{
Previous();
}
else if (keyData == Keys.Down)
{
Next();
}
else if (keyData == Keys.Home)
{
First();
}
else if (keyData == Keys.End)
{
End();
}
return base.ProcessCmdKey(ref msg, keyData);
}
///
/// 选中第一个
///
public void First()
{
if (Rows == null || Rows.Count <= 0)
return;
Control c = null;
c = (Rows[0] as Control);
SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = 0 });
}
///
/// 选中上一个
///
public void Previous()
{
if (Rows == null || Rows.Count <= 0)
return;
Control c = null;
int index = Rows.IndexOf(m_selectRow);
if (index - 1 >= 0)
{
c = (Rows[index - 1] as Control);
SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = index - 1 });
}
}
///
/// 选中下一个
///
public void Next()
{
if (Rows == null || Rows.Count <= 0)
return;
Control c = null;
int index = Rows.IndexOf(m_selectRow);
if (index + 1 < Rows.Count)
{
c = (Rows[index + 1] as Control);
SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = index + 1 });
}
}
///
/// 选中最后一个
///
public void End()
{
if (Rows == null || Rows.Count <= 0)
return;
Control c = null;
c = (Rows[Rows.Count - 1] as Control);
SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = Rows.Count - 1 });
}
#endregion
#region 事件
///
/// Rows the source changed.
///
/// The sender.
/// The instance containing the event data.
void RowSourceChanged(object sender, DataGridViewEventArgs e)
{
if (RowSourceChangedEvent != null)
RowSourceChangedEvent(sender, e);
}
///
/// Sets the select row.
///
/// The item.
/// The instance containing the event data.
private void SetSelectRow(Control item, DataGridViewEventArgs e)
{
try
{
ControlHelper.FreezeControl(this, true);
if (item == null)
return;
if (item.Visible == false)
return;
this.FindForm().ActiveControl = this;
this.FindForm().ActiveControl = item;
if (m_selectRow != item)
{
if (m_selectRow != null)
{
m_selectRow.SetSelect(false);
}
m_selectRow = item as IDataGridViewRow;
m_selectRow.SetSelect(true);
if (this.panRow.Controls.Count > 0)
{
if (item.Location.Y < 0)
{
this.panRow.AutoScrollPosition = new Point(0, Math.Abs(this.panRow.Controls[this.panRow.Controls.Count - 1].Location.Y) + item.Location.Y);
}
else if (item.Location.Y + m_rowHeight > this.panRow.Height)
{
this.panRow.AutoScrollPosition = new Point(0, Math.Abs(this.panRow.AutoScrollPosition.Y) + item.Location.Y - this.panRow.Height + m_rowHeight);
}
}
}
if (ItemClick != null)
{
ItemClick(item, e);
}
}
finally
{
ControlHelper.FreezeControl(this, false);
}
}
#endregion
private void UCDataGridView_SizeChanged(object sender, EventArgs e)
{
//LoadColumns();
//ReloadSource();
}
private void UCDataGridView_Scroll(object sender, ScrollEventArgs e)
{
//if (e.ScrollOrientation == ScrollOrientation.VerticalScroll)
//{
// panHead.Location = new Point(0, this.VerticalScroll.Value + this.panRow.Location.Y - panHead.Height - 2);
//}
}
private void panRow_Scroll(object sender, ScrollEventArgs e)
{
if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll && this.panRow.Controls.Count > 0)
{
Console.WriteLine(this.panRow.HorizontalScroll.Value);
Console.WriteLine(this.panRow.Controls[0].Location.X);
panHead.Location = new Point(this.panRow.HorizontalScroll.Value * -1, 0);
}
}
}
}