官网

http://www.hzhcontrols.com

前提

入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章。

GitHub:https://github.com/kwwwvagaa/NetWinformControl

码云:https://gitee.com/kwwwvagaa/net_winform_custom_control.git

如果觉得写的还行,请点个 star 支持一下吧

欢迎前来交流探讨: 企鹅群568015492 

idkey=6e08741ef16fe53bf0314c1c9e336c4f626047943a8b76bac062361bab6b4f8d">

目录

https://www.cnblogs.com/bfyx/p/11364884.html

准备工作

表格控件将拆分为2部分,1:行元素控件,2:列表控件

为了具有更好的扩展性,更加的open,使用接口对行元素进行约束,当行样式或功能不满足你的需求的时候,可以自定义一个行元素,实现接口控件,然后将类型指定给列表控件即可

表格控件用到了分页控件,如果你还没有对分页控件进行了解,请移步查看

(十二)c#Winform自定义控件-分页控件

开始

定义一些辅助东西

  1. public class DataGridViewCellEntity
  2. {
  3. public string Title { get; set; }
  4. public int Width { get; set; }
  5. public System.Windows.Forms.SizeType WidthType { get; set; }
  6.  
  7. }
  1. public class DataGridViewEventArgs : EventArgs
  2. {
  3. public Control CellControl { get; set; }
  4. public int CellIndex { get; set; }
  5. public int RowIndex { get; set; }
  6.  
  7. }
  1. [Serializable]
  2. [ComVisible(true)]
  3. public delegate void DataGridViewEventHandler(object sender, DataGridViewEventArgs e);
  1. public class DataGridViewColumnEntity
  2. {
  3. public string HeadText { get; set; }
  4. public int Width { get; set; }
  5. public System.Windows.Forms.SizeType WidthType { get; set; }
  6. public string DataField { get; set; }
  7. public Func<object, string> Format { get; set; }
  8. }

定义行接口

  1. public interface IDataGridViewRow
  2. {
  3. /// <summary>
  4. /// CheckBox选中事件
  5. /// </summary>
  6. event DataGridViewEventHandler CheckBoxChangeEvent;
  7. /// <summary>
  8. /// 点击单元格事件
  9. /// </summary>
  10. event DataGridViewEventHandler CellClick;
  11. /// <summary>
  12. /// 数据源改变事件
  13. /// </summary>
  14. event DataGridViewEventHandler SourceChanged;
  15. /// <summary>
  16. /// 列参数,用于创建列数和宽度
  17. /// </summary>
  18. List<DataGridViewColumnEntity> Columns { get; set; }
  19. bool IsShowCheckBox { get; set; }
  20. /// <summary>
  21. /// 是否选中
  22. /// </summary>
  23. bool IsChecked { get; set; }
  24.  
  25. /// <summary>
  26. /// 数据源
  27. /// </summary>
  28. object DataSource { get; set; }
  29. /// <summary>
  30. /// 添加单元格元素,仅做添加控件操作,不做数据绑定,数据绑定使用BindingCells
  31. /// </summary>
  32. void ReloadCells();
  33. /// <summary>
  34. /// 绑定数据到Cell
  35. /// </summary>
  36. /// <param name="intIndex">cell下标</param>
  37. /// <returns>返回true则表示已处理过,否则将进行默认绑定(通常只针对有Text值的控件)</returns>
  38. void BindingCellData();
  39. /// <summary>
  40. /// 设置选中状态,通常为设置颜色即可
  41. /// </summary>
  42. /// <param name="blnSelected">是否选中</param>
  43. void SetSelect(bool blnSelected);
  44. }

创建行控件

添加一个用户控件,命名UCDataGridViewRow,实现接口IDataGridViewRow

属性

  1. #region 属性
  2. public event DataGridViewEventHandler CheckBoxChangeEvent;
  3.  
  4. public event DataGridViewEventHandler CellClick;
  5.  
  6. public event DataGridViewEventHandler SourceChanged;
  7.  
  8. public List<DataGridViewColumnEntity> Columns
  9. {
  10. get;
  11. set;
  12. }
  13.  
  14. public object DataSource
  15. {
  16. get;
  17. set;
  18. }
  19.  
  20. public bool IsShowCheckBox
  21. {
  22. get;
  23. set;
  24. }
  25. private bool m_isChecked;
  26. public bool IsChecked
  27. {
  28. get
  29. {
  30. return m_isChecked;
  31. }
  32.  
  33. set
  34. {
  35. if (m_isChecked != value)
  36. {
  37. m_isChecked = value;
  38. (this.panCells.Controls.Find("check", false)[] as UCCheckBox).Checked = value;
  39. }
  40. }
  41. }
  42.  
  43. #endregion

实现接口

  1. public void BindingCellData()
  2. {
  3. for (int i = ; i < Columns.Count; i++)
  4. {
  5. DataGridViewColumnEntity com = Columns[i];
  6. var cs = this.panCells.Controls.Find("lbl_" + com.DataField, false);
  7. if (cs != null && cs.Length > )
  8. {
  9. var pro = DataSource.GetType().GetProperty(com.DataField);
  10. if (pro != null)
  11. {
  12. var value = pro.GetValue(DataSource, null);
  13. if (com.Format != null)
  14. {
  15. cs[].Text = com.Format(value);
  16. }
  17. else
  18. {
  19. cs[].Text = value.ToStringExt();
  20. }
  21. }
  22. }
  23. }
  24. }
  25.  
  26. public void SetSelect(bool blnSelected)
  27. {
  28. if (blnSelected)
  29. {
  30. this.BackColor = Color.FromArgb(, , );
  31. }
  32. else
  33. {
  34. this.BackColor = Color.Transparent;
  35. }
  36. }
  37.  
  38. public void ReloadCells()
  39. {
  40. try
  41. {
  42. ControlHelper.FreezeControl(this, true);
  43. this.panCells.Controls.Clear();
  44. this.panCells.ColumnStyles.Clear();
  45.  
  46. int intColumnsCount = Columns.Count();
  47. if (Columns != null && intColumnsCount > )
  48. {
  49. if (IsShowCheckBox)
  50. {
  51. intColumnsCount++;
  52. }
  53. this.panCells.ColumnCount = intColumnsCount;
  54. for (int i = ; i < intColumnsCount; i++)
  55. {
  56. Control c = null;
  57. if (i == && IsShowCheckBox)
  58. {
  59. this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F));
  60.  
  61. UCCheckBox box = new UCCheckBox();
  62. box.Name = "check";
  63. box.TextValue = "";
  64. box.Size = new Size(, );
  65. box.Dock = DockStyle.Fill;
  66. box.CheckedChangeEvent += (a, b) =>
  67. {
  68. IsChecked = box.Checked;
  69. if (CheckBoxChangeEvent != null)
  70. {
  71. CheckBoxChangeEvent(a, new DataGridViewEventArgs()
  72. {
  73. CellControl = box,
  74. CellIndex =
  75. });
  76. }
  77. };
  78. c = box;
  79. }
  80. else
  81. {
  82. var item = Columns[i - (IsShowCheckBox ? : )];
  83. this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width));
  84.  
  85. Label lbl = new Label();
  86. lbl.Tag = i - (IsShowCheckBox ? : );
  87. lbl.Name = "lbl_" + item.DataField;
  88. lbl.Font = new Font("微软雅黑", );
  89. lbl.ForeColor = Color.Black;
  90. lbl.AutoSize = false;
  91. lbl.Dock = DockStyle.Fill;
  92. lbl.TextAlign = ContentAlignment.MiddleCenter;
  93. lbl.MouseDown += (a, b) =>
  94. {
  95. Item_MouseDown(a, b);
  96. };
  97. c = lbl;
  98. }
  99. this.panCells.Controls.Add(c, i, );
  100. }
  101.  
  102. }
  103. }
  104. finally
  105. {
  106. ControlHelper.FreezeControl(this, false);
  107. }
  108. }

节点选中事件

  1. void Item_MouseDown(object sender, MouseEventArgs e)
  2. {
  3. if (CellClick != null)
  4. {
  5. CellClick(sender, new DataGridViewEventArgs()
  6. {
  7. CellControl = this,
  8. CellIndex = (sender as Control).Tag.ToInt()
  9. });
  10. }
  11. }

完整的代码

  1. // 版权所有 黄正辉 交流群:568015492 QQ:623128629
  2. // 文件名称:UCDataGridViewRow.cs
  3. // 创建日期:2019-08-15 15:59:31
  4. // 功能描述:DataGridView
  5. // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Drawing;
  10. using System.Data;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Windows.Forms;
  14.  
  15. namespace HZH_Controls.Controls
  16. {
  17. [ToolboxItem(false)]
  18. public partial class UCDataGridViewRow : UserControl, IDataGridViewRow
  19. {
  20.  
  21. #region 属性
  22. public event DataGridViewEventHandler CheckBoxChangeEvent;
  23.  
  24. public event DataGridViewEventHandler CellClick;
  25.  
  26. public event DataGridViewEventHandler SourceChanged;
  27.  
  28. public List<DataGridViewColumnEntity> Columns
  29. {
  30. get;
  31. set;
  32. }
  33.  
  34. public object DataSource
  35. {
  36. get;
  37. set;
  38. }
  39.  
  40. public bool IsShowCheckBox
  41. {
  42. get;
  43. set;
  44. }
  45. private bool m_isChecked;
  46. public bool IsChecked
  47. {
  48. get
  49. {
  50. return m_isChecked;
  51. }
  52.  
  53. set
  54. {
  55. if (m_isChecked != value)
  56. {
  57. m_isChecked = value;
  58. (this.panCells.Controls.Find("check", false)[] as UCCheckBox).Checked = value;
  59. }
  60. }
  61. }
  62.  
  63. #endregion
  64.  
  65. public UCDataGridViewRow()
  66. {
  67. InitializeComponent();
  68. }
  69.  
  70. public void BindingCellData()
  71. {
  72. for (int i = ; i < Columns.Count; i++)
  73. {
  74. DataGridViewColumnEntity com = Columns[i];
  75. var cs = this.panCells.Controls.Find("lbl_" + com.DataField, false);
  76. if (cs != null && cs.Length > )
  77. {
  78. var pro = DataSource.GetType().GetProperty(com.DataField);
  79. if (pro != null)
  80. {
  81. var value = pro.GetValue(DataSource, null);
  82. if (com.Format != null)
  83. {
  84. cs[].Text = com.Format(value);
  85. }
  86. else
  87. {
  88. cs[].Text = value.ToStringExt();
  89. }
  90. }
  91. }
  92. }
  93. }
  94.  
  95. void Item_MouseDown(object sender, MouseEventArgs e)
  96. {
  97. if (CellClick != null)
  98. {
  99. CellClick(sender, new DataGridViewEventArgs()
  100. {
  101. CellControl = this,
  102. CellIndex = (sender as Control).Tag.ToInt()
  103. });
  104. }
  105. }
  106.  
  107. public void SetSelect(bool blnSelected)
  108. {
  109. if (blnSelected)
  110. {
  111. this.BackColor = Color.FromArgb(, , );
  112. }
  113. else
  114. {
  115. this.BackColor = Color.Transparent;
  116. }
  117. }
  118.  
  119. public void ReloadCells()
  120. {
  121. try
  122. {
  123. ControlHelper.FreezeControl(this, true);
  124. this.panCells.Controls.Clear();
  125. this.panCells.ColumnStyles.Clear();
  126.  
  127. int intColumnsCount = Columns.Count();
  128. if (Columns != null && intColumnsCount > )
  129. {
  130. if (IsShowCheckBox)
  131. {
  132. intColumnsCount++;
  133. }
  134. this.panCells.ColumnCount = intColumnsCount;
  135. for (int i = ; i < intColumnsCount; i++)
  136. {
  137. Control c = null;
  138. if (i == && IsShowCheckBox)
  139. {
  140. this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F));
  141.  
  142. UCCheckBox box = new UCCheckBox();
  143. box.Name = "check";
  144. box.TextValue = "";
  145. box.Size = new Size(, );
  146. box.Dock = DockStyle.Fill;
  147. box.CheckedChangeEvent += (a, b) =>
  148. {
  149. IsChecked = box.Checked;
  150. if (CheckBoxChangeEvent != null)
  151. {
  152. CheckBoxChangeEvent(a, new DataGridViewEventArgs()
  153. {
  154. CellControl = box,
  155. CellIndex =
  156. });
  157. }
  158. };
  159. c = box;
  160. }
  161. else
  162. {
  163. var item = Columns[i - (IsShowCheckBox ? : )];
  164. this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width));
  165.  
  166. Label lbl = new Label();
  167. lbl.Tag = i - (IsShowCheckBox ? : );
  168. lbl.Name = "lbl_" + item.DataField;
  169. lbl.Font = new Font("微软雅黑", );
  170. lbl.ForeColor = Color.Black;
  171. lbl.AutoSize = false;
  172. lbl.Dock = DockStyle.Fill;
  173. lbl.TextAlign = ContentAlignment.MiddleCenter;
  174. lbl.MouseDown += (a, b) =>
  175. {
  176. Item_MouseDown(a, b);
  177. };
  178. c = lbl;
  179. }
  180. this.panCells.Controls.Add(c, i, );
  181. }
  182.  
  183. }
  184. }
  185. finally
  186. {
  187. ControlHelper.FreezeControl(this, false);
  188. }
  189. }
  190.  
  191. }
  192. }
  1. namespace HZH_Controls.Controls
  2. {
  3. partial class UCDataGridViewRow
  4. {
  5. /// <summary>
  6. /// 必需的设计器变量。
  7. /// </summary>
  8. private System.ComponentModel.IContainer components = null;
  9.  
  10. /// <summary>
  11. /// 清理所有正在使用的资源。
  12. /// </summary>
  13. /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
  14. protected override void Dispose(bool disposing)
  15. {
  16. if (disposing && (components != null))
  17. {
  18. components.Dispose();
  19. }
  20. base.Dispose(disposing);
  21. }
  22.  
  23. #region 组件设计器生成的代码
  24.  
  25. /// <summary>
  26. /// 设计器支持所需的方法 - 不要
  27. /// 使用代码编辑器修改此方法的内容。
  28. /// </summary>
  29. private void InitializeComponent()
  30. {
  31. this.ucSplitLine_H1 = new HZH_Controls.Controls.UCSplitLine_H();
  32. this.panCells = new System.Windows.Forms.TableLayoutPanel();
  33. this.SuspendLayout();
  34. //
  35. // ucSplitLine_H1
  36. //
  37. this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)()))), ((int)(((byte)()))), ((int)(((byte)()))));
  38. this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom;
  39. this.ucSplitLine_H1.Location = new System.Drawing.Point(, );
  40. this.ucSplitLine_H1.Name = "ucSplitLine_H1";
  41. this.ucSplitLine_H1.Size = new System.Drawing.Size(, );
  42. this.ucSplitLine_H1.TabIndex = ;
  43. this.ucSplitLine_H1.TabStop = false;
  44. //
  45. // panCells
  46. //
  47. this.panCells.ColumnCount = ;
  48. this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
  49. this.panCells.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
  50. this.panCells.Dock = System.Windows.Forms.DockStyle.Fill;
  51. this.panCells.Location = new System.Drawing.Point(, );
  52. this.panCells.Name = "panCells";
  53. this.panCells.RowCount = ;
  54. this.panCells.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
  55. this.panCells.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
  56. this.panCells.Size = new System.Drawing.Size(, );
  57. this.panCells.TabIndex = ;
  58. //
  59. // UCDataGridViewItem
  60. //
  61. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
  62. this.BackColor = System.Drawing.Color.White;
  63. this.Controls.Add(this.panCells);
  64. this.Controls.Add(this.ucSplitLine_H1);
  65. this.Name = "UCDataGridViewItem";
  66. this.Size = new System.Drawing.Size(, );
  67. this.ResumeLayout(false);
  68.  
  69. }
  70.  
  71. #endregion
  72.  
  73. private UCSplitLine_H ucSplitLine_H1;
  74. private System.Windows.Forms.TableLayoutPanel panCells;
  75. }
  76. }

接下来就是列表控件了

添加一个用户控件,命名UCDataGridView

属性

  1. #region 属性
  2. private Font m_headFont = new Font("微软雅黑", 12F);
  3. /// <summary>
  4. /// 标题字体
  5. /// </summary>
  6. [Description("标题字体"), Category("自定义")]
  7. public Font HeadFont
  8. {
  9. get { return m_headFont; }
  10. set { m_headFont = value; }
  11. }
  12. private Color m_headTextColor = Color.Black;
  13. /// <summary>
  14. /// 标题字体颜色
  15. /// </summary>
  16. [Description("标题文字颜色"), Category("自定义")]
  17. public Color HeadTextColor
  18. {
  19. get { return m_headTextColor; }
  20. set { m_headTextColor = value; }
  21. }
  22.  
  23. private bool m_isShowHead = true;
  24. /// <summary>
  25. /// 是否显示标题
  26. /// </summary>
  27. [Description("是否显示标题"), Category("自定义")]
  28. public bool IsShowHead
  29. {
  30. get { return m_isShowHead; }
  31. set
  32. {
  33. m_isShowHead = value;
  34. panHead.Visible = value;
  35. if (m_page != null)
  36. {
  37. ResetShowCount();
  38. m_page.PageSize = m_showCount;
  39. }
  40. }
  41. }
  42. private int m_headHeight = ;
  43. /// <summary>
  44. /// 标题高度
  45. /// </summary>
  46. [Description("标题高度"), Category("自定义")]
  47. public int HeadHeight
  48. {
  49. get { return m_headHeight; }
  50. set
  51. {
  52. m_headHeight = value;
  53. panHead.Height = value;
  54. }
  55. }
  56.  
  57. private bool m_isShowCheckBox = false;
  58. /// <summary>
  59. /// 是否显示复选框
  60. /// </summary>
  61. [Description("是否显示选择框"), Category("自定义")]
  62. public bool IsShowCheckBox
  63. {
  64. get { return m_isShowCheckBox; }
  65. set
  66. {
  67. if (value != m_isShowCheckBox)
  68. {
  69. m_isShowCheckBox = value;
  70. LoadColumns();
  71. }
  72. }
  73. }
  74.  
  75. private int m_rowHeight = ;
  76. /// <summary>
  77. /// 行高
  78. /// </summary>
  79. [Description("数据行高"), Category("自定义")]
  80. public int RowHeight
  81. {
  82. get { return m_rowHeight; }
  83. set { m_rowHeight = value; }
  84. }
  85.  
  86. private int m_showCount = ;
  87. /// <summary>
  88. ///
  89. /// </summary>
  90. [Description("可显示个数"), Category("自定义")]
  91. public int ShowCount
  92. {
  93. get { return m_showCount; }
  94. private set
  95. {
  96. m_showCount = value;
  97. if (m_page != null)
  98. {
  99. m_page.PageSize = value;
  100. }
  101. }
  102. }
  103.  
  104. private List<DataGridViewColumnEntity> m_columns;
  105. /// <summary>
  106. /// 列
  107. /// </summary>
  108. [Description("列"), Category("自定义")]
  109. public List<DataGridViewColumnEntity> Columns
  110. {
  111. get { return m_columns; }
  112. set
  113. {
  114. m_columns = value;
  115. LoadColumns();
  116. }
  117. }
  118.  
  119. private object m_dataSource;
  120. /// <summary>
  121. /// 数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的DataSource
  122. /// </summary>
  123. [Description("数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的DataSource"), Category("自定义")]
  124. public object DataSource
  125. {
  126. get { return m_dataSource; }
  127. set
  128. {
  129. if (value == null)
  130. return;
  131. if (!(m_dataSource is DataTable) && (!typeof(IList).IsAssignableFrom(value.GetType())))
  132. {
  133. throw new Exception("数据源不是有效的数据类型,请使用Datatable或列表");
  134. }
  135.  
  136. m_dataSource = value;
  137. ReloadSource();
  138. }
  139. }
  140.  
  141. public List<IDataGridViewRow> Rows { get; private set; }
  142.  
  143. private Type m_rowType = typeof(UCDataGridViewRow);
  144. /// <summary>
  145. /// 行元素类型,默认UCDataGridViewItem
  146. /// </summary>
  147. [Description("行控件类型,默认UCDataGridViewRow,如果不满足请自定义行控件实现接口IDataGridViewRow"), Category("自定义")]
  148. public Type RowType
  149. {
  150. get { return m_rowType; }
  151. set
  152. {
  153. if (value == null)
  154. return;
  155. if (!typeof(IDataGridViewRow).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
  156. throw new Exception("行控件没有实现IDataGridViewRow接口");
  157. m_rowType = value;
  158. }
  159. }
  160. IDataGridViewRow m_selectRow = null;
  161. /// <summary>
  162. /// 选中的节点
  163. /// </summary>
  164. [Description("选中行"), Category("自定义")]
  165. public IDataGridViewRow SelectRow
  166. {
  167. get { return m_selectRow; }
  168. private set { m_selectRow = value; }
  169. }
  170.  
  171. /// <summary>
  172. /// 选中的行,如果显示CheckBox,则以CheckBox选中为准
  173. /// </summary>
  174. [Description("选中的行,如果显示CheckBox,则以CheckBox选中为准"), Category("自定义")]
  175. public List<IDataGridViewRow> SelectRows
  176. {
  177. get
  178. {
  179. if (m_isShowCheckBox)
  180. {
  181. return Rows.FindAll(p => p.IsChecked);
  182. }
  183. else
  184. return new List<IDataGridViewRow>() { m_selectRow };
  185. }
  186. }
  187.  
  188. private UCPagerControlBase m_page = null;
  189. /// <summary>
  190. /// 翻页控件
  191. /// </summary>
  192. [Description("翻页控件,如果UCPagerControl不满足你的需求,请自定义翻页控件并继承UCPagerControlBase"), Category("自定义")]
  193. public UCPagerControlBase Page
  194. {
  195. get { return m_page; }
  196. set
  197. {
  198. m_page = value;
  199. if (value != null)
  200. {
  201. if (!typeof(IPageControl).IsAssignableFrom(value.GetType()) || !value.GetType().IsSubclassOf(typeof(UCPagerControlBase)))
  202. throw new Exception("翻页控件没有继承UCPagerControlBase");
  203. panPage.Visible = value != null;
  204. m_page.ShowSourceChanged += page_ShowSourceChanged;
  205. m_page.Dock = DockStyle.Fill;
  206. this.panPage.Controls.Clear();
  207. this.panPage.Controls.Add(m_page);
  208. ResetShowCount();
  209. m_page.PageSize = ShowCount;
  210. this.DataSource = m_page.GetCurrentSource();
  211. }
  212. else
  213. {
  214. m_page = null;
  215. }
  216. }
  217. }
  218.  
  219. void page_ShowSourceChanged(object currentSource)
  220. {
  221. this.DataSource = currentSource;
  222. }
  223.  
  224. #region 事件
  225. [Description("选中标题选择框事件"), Category("自定义")]
  226. public EventHandler HeadCheckBoxChangeEvent;
  227. [Description("标题点击事件"), Category("自定义")]
  228. public EventHandler HeadColumnClickEvent;
  229. [Description("项点击事件"), Category("自定义")]
  230. public event DataGridViewEventHandler ItemClick;
  231. [Description("数据源改变事件"), Category("自定义")]
  232. public event DataGridViewEventHandler SourceChanged;
  233. #endregion
  234. #endregion

一些私有的方法

  1. #region 私有方法
  2. #region 加载column
  3. /// <summary>
  4. /// 功能描述:加载column
  5. /// 作  者:HZH
  6. /// 创建日期:2019-08-08 17:51:50
  7. /// 任务编号:POS
  8. /// </summary>
  9. private void LoadColumns()
  10. {
  11. try
  12. {
  13. if (DesignMode)
  14. { return; }
  15.  
  16. ControlHelper.FreezeControl(this.panHead, true);
  17. this.panColumns.Controls.Clear();
  18. this.panColumns.ColumnStyles.Clear();
  19.  
  20. if (m_columns != null && m_columns.Count() > )
  21. {
  22. int intColumnsCount = m_columns.Count();
  23. if (m_isShowCheckBox)
  24. {
  25. intColumnsCount++;
  26. }
  27. this.panColumns.ColumnCount = intColumnsCount;
  28. for (int i = ; i < intColumnsCount; i++)
  29. {
  30. Control c = null;
  31. if (i == && m_isShowCheckBox)
  32. {
  33. this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F));
  34.  
  35. UCCheckBox box = new UCCheckBox();
  36. box.TextValue = "";
  37. box.Size = new Size(, );
  38. box.CheckedChangeEvent += (a, b) =>
  39. {
  40. Rows.ForEach(p => p.IsChecked = box.Checked);
  41. if (HeadCheckBoxChangeEvent != null)
  42. {
  43. HeadCheckBoxChangeEvent(a, b);
  44. }
  45. };
  46. c = box;
  47. }
  48. else
  49. {
  50. var item = m_columns[i - (m_isShowCheckBox ? : )];
  51. this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width));
  52. Label lbl = new Label();
  53. lbl.Name = "dgvColumns_" + i;
  54. lbl.Text = item.HeadText;
  55. lbl.Font = m_headFont;
  56. lbl.ForeColor = m_headTextColor;
  57. lbl.TextAlign = ContentAlignment.MiddleCenter;
  58. lbl.AutoSize = false;
  59. lbl.Dock = DockStyle.Fill;
  60. lbl.MouseDown += (a, b) =>
  61. {
  62. if (HeadColumnClickEvent != null)
  63. {
  64. HeadColumnClickEvent(a, b);
  65. }
  66. };
  67. c = lbl;
  68. }
  69. this.panColumns.Controls.Add(c, i, );
  70. }
  71.  
  72. }
  73. }
  74. finally
  75. {
  76. ControlHelper.FreezeControl(this.panHead, false);
  77. }
  78. }
  79. #endregion
  80.  
  81. /// <summary>
  82. /// 功能描述:获取显示个数
  83. /// 作  者:HZH
  84. /// 创建日期:2019-03-05 10:02:58
  85. /// 任务编号:POS
  86. /// </summary>
  87. /// <returns>返回值</returns>
  88. private void ResetShowCount()
  89. {
  90. if (DesignMode)
  91. { return; }
  92. ShowCount = this.panRow.Height / (m_rowHeight);
  93. int intCha = this.panRow.Height % (m_rowHeight);
  94. m_rowHeight += intCha / ShowCount;
  95. }
  96. #endregion

几个事件

  1. #region 事件
  2. void RowSourceChanged(object sender, DataGridViewEventArgs e)
  3. {
  4. if (SourceChanged != null)
  5. SourceChanged(sender, e);
  6. }
  7. private void SetSelectRow(Control item, DataGridViewEventArgs e)
  8. {
  9. try
  10. {
  11. ControlHelper.FreezeControl(this, true);
  12. if (item == null)
  13. return;
  14. if (item.Visible == false)
  15. return;
  16. this.FindForm().ActiveControl = this;
  17. this.FindForm().ActiveControl = item;
  18. if (m_selectRow != null)
  19. {
  20. if (m_selectRow == item)
  21. return;
  22. m_selectRow.SetSelect(false);
  23. }
  24. m_selectRow = item as IDataGridViewRow;
  25. m_selectRow.SetSelect(true);
  26. if (ItemClick != null)
  27. {
  28. ItemClick(item, e);
  29. }
  30. if (this.panRow.Controls.Count > )
  31. {
  32. if (item.Location.Y < )
  33. {
  34. this.panRow.AutoScrollPosition = new Point(, Math.Abs(this.panRow.Controls[this.panRow.Controls.Count - ].Location.Y) + item.Location.Y);
  35. }
  36. else if (item.Location.Y + m_rowHeight > this.panRow.Height)
  37. {
  38. this.panRow.AutoScrollPosition = new Point(, Math.Abs(this.panRow.AutoScrollPosition.Y) + item.Location.Y - this.panRow.Height + m_rowHeight);
  39. }
  40. }
  41. }
  42. finally
  43. {
  44. ControlHelper.FreezeControl(this, false);
  45. }
  46. }
  47. private void UCDataGridView_Resize(object sender, EventArgs e)
  48. {
  49. ResetShowCount();
  50. ReloadSource();
  51. }
  52. #endregion

对外公开的函数

  1. #region 公共函数
  2. /// <summary>
  3. /// 刷新数据
  4. /// </summary>
  5. public void ReloadSource()
  6. {
  7. if (DesignMode)
  8. { return; }
  9. try
  10. {
  11. if (m_columns == null || m_columns.Count <= )
  12. return;
  13.  
  14. ControlHelper.FreezeControl(this.panRow, true);
  15. this.panRow.Controls.Clear();
  16. Rows = new List<IDataGridViewRow>();
  17. if (m_dataSource != null)
  18. {
  19. int intIndex = ;
  20. Control lastItem = null;
  21.  
  22. int intSourceCount = ;
  23. if (m_dataSource is DataTable)
  24. {
  25. intSourceCount = (m_dataSource as DataTable).Rows.Count;
  26. }
  27. else if (typeof(IList).IsAssignableFrom(m_dataSource.GetType()))
  28. {
  29. intSourceCount = (m_dataSource as IList).Count;
  30. }
  31.  
  32. foreach (Control item in this.panRow.Controls)
  33. {
  34.  
  35. if (intIndex >= intSourceCount)
  36. {
  37. item.Visible = false;
  38. }
  39. else
  40. {
  41. var row = (item as IDataGridViewRow);
  42. row.IsShowCheckBox = m_isShowCheckBox;
  43. if (m_dataSource is DataTable)
  44. {
  45. row.DataSource = (m_dataSource as DataTable).Rows[intIndex];
  46. }
  47. else
  48. {
  49. row.DataSource = (m_dataSource as IList)[intIndex];
  50. }
  51. row.BindingCellData();
  52. item.Height = m_rowHeight;
  53. item.Visible = true;
  54. item.BringToFront();
  55. if (lastItem == null)
  56. lastItem = item;
  57. Rows.Add(row);
  58. }
  59. intIndex++;
  60. }
  61.  
  62. if (intIndex < intSourceCount)
  63. {
  64. for (int i = intIndex; i < intSourceCount; i++)
  65. {
  66. IDataGridViewRow row = (IDataGridViewRow)Activator.CreateInstance(m_rowType);
  67. if (m_dataSource is DataTable)
  68. {
  69. row.DataSource = (m_dataSource as DataTable).Rows[i];
  70. }
  71. else
  72. {
  73. row.DataSource = (m_dataSource as IList)[i];
  74. }
  75. row.Columns = m_columns;
  76. List<Control> lstCells = new List<Control>();
  77. row.IsShowCheckBox = m_isShowCheckBox;
  78. row.ReloadCells();
  79. row.BindingCellData();
  80.  
  81. Control rowControl = (row as Control);
  82. rowControl.Height = m_rowHeight;
  83. this.panRow.Controls.Add(rowControl);
  84. rowControl.Dock = DockStyle.Top;
  85. row.CellClick += (a, b) => { SetSelectRow(rowControl, b); };
  86. row.CheckBoxChangeEvent += (a, b) => { SetSelectRow(rowControl, b); };
  87. row.SourceChanged += RowSourceChanged;
  88. rowControl.BringToFront();
  89. Rows.Add(row);
  90.  
  91. if (lastItem == null)
  92. lastItem = rowControl;
  93. }
  94. }
  95. if (lastItem != null && intSourceCount == m_showCount)
  96. {
  97. lastItem.Height = this.panRow.Height - (m_showCount - ) * m_rowHeight;
  98. }
  99. }
  100. }
  101. finally
  102. {
  103. ControlHelper.FreezeControl(this.panRow, false);
  104. }
  105. }
  106.  
  107. /// <summary>
  108. /// 快捷键
  109. /// </summary>
  110. /// <param name="msg"></param>
  111. /// <param name="keyData"></param>
  112. /// <returns></returns>
  113. protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
  114. {
  115. if (keyData == Keys.Up)
  116. {
  117. Previous();
  118. }
  119. else if (keyData == Keys.Down)
  120. {
  121. Next();
  122. }
  123. else if (keyData == Keys.Home)
  124. {
  125. First();
  126. }
  127. else if (keyData == Keys.End)
  128. {
  129. End();
  130. }
  131. return base.ProcessCmdKey(ref msg, keyData);
  132. }
  133. /// <summary>
  134. /// 选中第一个
  135. /// </summary>
  136. public void First()
  137. {
  138. if (Rows == null || Rows.Count <= )
  139. return;
  140. Control c = null;
  141. c = (Rows[] as Control);
  142. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = });
  143. }
  144. /// <summary>
  145. /// 选中上一个
  146. /// </summary>
  147. public void Previous()
  148. {
  149. if (Rows == null || Rows.Count <= )
  150. return;
  151. Control c = null;
  152.  
  153. int index = Rows.IndexOf(m_selectRow);
  154. if (index - >= )
  155. {
  156. c = (Rows[index - ] as Control);
  157. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = index - });
  158. }
  159. }
  160. /// <summary>
  161. /// 选中下一个
  162. /// </summary>
  163. public void Next()
  164. {
  165. if (Rows == null || Rows.Count <= )
  166. return;
  167. Control c = null;
  168.  
  169. int index = Rows.IndexOf(m_selectRow);
  170. if (index + < Rows.Count)
  171. {
  172. c = (Rows[index + ] as Control);
  173. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = index + });
  174. }
  175. }
  176. /// <summary>
  177. /// 选中最后一个
  178. /// </summary>
  179. public void End()
  180. {
  181. if (Rows == null || Rows.Count <= )
  182. return;
  183. Control c = null;
  184. c = (Rows[Rows.Count - ] as Control);
  185. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = Rows.Count - });
  186. }
  187.  
  188. #endregion

完整代码

  1. // 版权所有 黄正辉 交流群:568015492 QQ:623128629
  2. // 文件名称:UCDataGridView.cs
  3. // 创建日期:2019-08-15 15:59:25
  4. // 功能描述:DataGridView
  5. // 项目地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
  6. using System;
  7. using System.Collections.Generic;
  8. using System.ComponentModel;
  9. using System.Drawing;
  10. using System.Data;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Windows.Forms;
  14. using System.Collections;
  15.  
  16. namespace HZH_Controls.Controls
  17. {
  18. public partial class UCDataGridView : UserControl
  19. {
  20. #region 属性
  21. private Font m_headFont = new Font("微软雅黑", 12F);
  22. /// <summary>
  23. /// 标题字体
  24. /// </summary>
  25. [Description("标题字体"), Category("自定义")]
  26. public Font HeadFont
  27. {
  28. get { return m_headFont; }
  29. set { m_headFont = value; }
  30. }
  31. private Color m_headTextColor = Color.Black;
  32. /// <summary>
  33. /// 标题字体颜色
  34. /// </summary>
  35. [Description("标题文字颜色"), Category("自定义")]
  36. public Color HeadTextColor
  37. {
  38. get { return m_headTextColor; }
  39. set { m_headTextColor = value; }
  40. }
  41.  
  42. private bool m_isShowHead = true;
  43. /// <summary>
  44. /// 是否显示标题
  45. /// </summary>
  46. [Description("是否显示标题"), Category("自定义")]
  47. public bool IsShowHead
  48. {
  49. get { return m_isShowHead; }
  50. set
  51. {
  52. m_isShowHead = value;
  53. panHead.Visible = value;
  54. if (m_page != null)
  55. {
  56. ResetShowCount();
  57. m_page.PageSize = m_showCount;
  58. }
  59. }
  60. }
  61. private int m_headHeight = ;
  62. /// <summary>
  63. /// 标题高度
  64. /// </summary>
  65. [Description("标题高度"), Category("自定义")]
  66. public int HeadHeight
  67. {
  68. get { return m_headHeight; }
  69. set
  70. {
  71. m_headHeight = value;
  72. panHead.Height = value;
  73. }
  74. }
  75.  
  76. private bool m_isShowCheckBox = false;
  77. /// <summary>
  78. /// 是否显示复选框
  79. /// </summary>
  80. [Description("是否显示选择框"), Category("自定义")]
  81. public bool IsShowCheckBox
  82. {
  83. get { return m_isShowCheckBox; }
  84. set
  85. {
  86. if (value != m_isShowCheckBox)
  87. {
  88. m_isShowCheckBox = value;
  89. LoadColumns();
  90. }
  91. }
  92. }
  93.  
  94. private int m_rowHeight = ;
  95. /// <summary>
  96. /// 行高
  97. /// </summary>
  98. [Description("数据行高"), Category("自定义")]
  99. public int RowHeight
  100. {
  101. get { return m_rowHeight; }
  102. set { m_rowHeight = value; }
  103. }
  104.  
  105. private int m_showCount = ;
  106. /// <summary>
  107. ///
  108. /// </summary>
  109. [Description("可显示个数"), Category("自定义")]
  110. public int ShowCount
  111. {
  112. get { return m_showCount; }
  113. private set
  114. {
  115. m_showCount = value;
  116. if (m_page != null)
  117. {
  118. m_page.PageSize = value;
  119. }
  120. }
  121. }
  122.  
  123. private List<DataGridViewColumnEntity> m_columns;
  124. /// <summary>
  125. /// 列
  126. /// </summary>
  127. [Description("列"), Category("自定义")]
  128. public List<DataGridViewColumnEntity> Columns
  129. {
  130. get { return m_columns; }
  131. set
  132. {
  133. m_columns = value;
  134. LoadColumns();
  135. }
  136. }
  137.  
  138. private object m_dataSource;
  139. /// <summary>
  140. /// 数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的DataSource
  141. /// </summary>
  142. [Description("数据源,支持列表或table,如果使用翻页控件,请使用翻页控件的DataSource"), Category("自定义")]
  143. public object DataSource
  144. {
  145. get { return m_dataSource; }
  146. set
  147. {
  148. if (value == null)
  149. return;
  150. if (!(m_dataSource is DataTable) && (!typeof(IList).IsAssignableFrom(value.GetType())))
  151. {
  152. throw new Exception("数据源不是有效的数据类型,请使用Datatable或列表");
  153. }
  154.  
  155. m_dataSource = value;
  156. ReloadSource();
  157. }
  158. }
  159.  
  160. public List<IDataGridViewRow> Rows { get; private set; }
  161.  
  162. private Type m_rowType = typeof(UCDataGridViewRow);
  163. /// <summary>
  164. /// 行元素类型,默认UCDataGridViewItem
  165. /// </summary>
  166. [Description("行控件类型,默认UCDataGridViewRow,如果不满足请自定义行控件实现接口IDataGridViewRow"), Category("自定义")]
  167. public Type RowType
  168. {
  169. get { return m_rowType; }
  170. set
  171. {
  172. if (value == null)
  173. return;
  174. if (!typeof(IDataGridViewRow).IsAssignableFrom(value) || !value.IsSubclassOf(typeof(Control)))
  175. throw new Exception("行控件没有实现IDataGridViewRow接口");
  176. m_rowType = value;
  177. }
  178. }
  179. IDataGridViewRow m_selectRow = null;
  180. /// <summary>
  181. /// 选中的节点
  182. /// </summary>
  183. [Description("选中行"), Category("自定义")]
  184. public IDataGridViewRow SelectRow
  185. {
  186. get { return m_selectRow; }
  187. private set { m_selectRow = value; }
  188. }
  189.  
  190. /// <summary>
  191. /// 选中的行,如果显示CheckBox,则以CheckBox选中为准
  192. /// </summary>
  193. [Description("选中的行,如果显示CheckBox,则以CheckBox选中为准"), Category("自定义")]
  194. public List<IDataGridViewRow> SelectRows
  195. {
  196. get
  197. {
  198. if (m_isShowCheckBox)
  199. {
  200. return Rows.FindAll(p => p.IsChecked);
  201. }
  202. else
  203. return new List<IDataGridViewRow>() { m_selectRow };
  204. }
  205. }
  206.  
  207. private UCPagerControlBase m_page = null;
  208. /// <summary>
  209. /// 翻页控件
  210. /// </summary>
  211. [Description("翻页控件,如果UCPagerControl不满足你的需求,请自定义翻页控件并继承UCPagerControlBase"), Category("自定义")]
  212. public UCPagerControlBase Page
  213. {
  214. get { return m_page; }
  215. set
  216. {
  217. m_page = value;
  218. if (value != null)
  219. {
  220. if (!typeof(IPageControl).IsAssignableFrom(value.GetType()) || !value.GetType().IsSubclassOf(typeof(UCPagerControlBase)))
  221. throw new Exception("翻页控件没有继承UCPagerControlBase");
  222. panPage.Visible = value != null;
  223. m_page.ShowSourceChanged += page_ShowSourceChanged;
  224. m_page.Dock = DockStyle.Fill;
  225. this.panPage.Controls.Clear();
  226. this.panPage.Controls.Add(m_page);
  227. ResetShowCount();
  228. m_page.PageSize = ShowCount;
  229. this.DataSource = m_page.GetCurrentSource();
  230. }
  231. else
  232. {
  233. m_page = null;
  234. }
  235. }
  236. }
  237.  
  238. void page_ShowSourceChanged(object currentSource)
  239. {
  240. this.DataSource = currentSource;
  241. }
  242.  
  243. #region 事件
  244. [Description("选中标题选择框事件"), Category("自定义")]
  245. public EventHandler HeadCheckBoxChangeEvent;
  246. [Description("标题点击事件"), Category("自定义")]
  247. public EventHandler HeadColumnClickEvent;
  248. [Description("项点击事件"), Category("自定义")]
  249. public event DataGridViewEventHandler ItemClick;
  250. [Description("数据源改变事件"), Category("自定义")]
  251. public event DataGridViewEventHandler SourceChanged;
  252. #endregion
  253. #endregion
  254.  
  255. public UCDataGridView()
  256. {
  257. InitializeComponent();
  258. }
  259.  
  260. #region 私有方法
  261. #region 加载column
  262. /// <summary>
  263. /// 功能描述:加载column
  264. /// 作  者:HZH
  265. /// 创建日期:2019-08-08 17:51:50
  266. /// 任务编号:POS
  267. /// </summary>
  268. private void LoadColumns()
  269. {
  270. try
  271. {
  272. if (DesignMode)
  273. { return; }
  274.  
  275. ControlHelper.FreezeControl(this.panHead, true);
  276. this.panColumns.Controls.Clear();
  277. this.panColumns.ColumnStyles.Clear();
  278.  
  279. if (m_columns != null && m_columns.Count() > )
  280. {
  281. int intColumnsCount = m_columns.Count();
  282. if (m_isShowCheckBox)
  283. {
  284. intColumnsCount++;
  285. }
  286. this.panColumns.ColumnCount = intColumnsCount;
  287. for (int i = ; i < intColumnsCount; i++)
  288. {
  289. Control c = null;
  290. if (i == && m_isShowCheckBox)
  291. {
  292. this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(SizeType.Absolute, 30F));
  293.  
  294. UCCheckBox box = new UCCheckBox();
  295. box.TextValue = "";
  296. box.Size = new Size(, );
  297. box.CheckedChangeEvent += (a, b) =>
  298. {
  299. Rows.ForEach(p => p.IsChecked = box.Checked);
  300. if (HeadCheckBoxChangeEvent != null)
  301. {
  302. HeadCheckBoxChangeEvent(a, b);
  303. }
  304. };
  305. c = box;
  306. }
  307. else
  308. {
  309. var item = m_columns[i - (m_isShowCheckBox ? : )];
  310. this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(item.WidthType, item.Width));
  311. Label lbl = new Label();
  312. lbl.Name = "dgvColumns_" + i;
  313. lbl.Text = item.HeadText;
  314. lbl.Font = m_headFont;
  315. lbl.ForeColor = m_headTextColor;
  316. lbl.TextAlign = ContentAlignment.MiddleCenter;
  317. lbl.AutoSize = false;
  318. lbl.Dock = DockStyle.Fill;
  319. lbl.MouseDown += (a, b) =>
  320. {
  321. if (HeadColumnClickEvent != null)
  322. {
  323. HeadColumnClickEvent(a, b);
  324. }
  325. };
  326. c = lbl;
  327. }
  328. this.panColumns.Controls.Add(c, i, );
  329. }
  330.  
  331. }
  332. }
  333. finally
  334. {
  335. ControlHelper.FreezeControl(this.panHead, false);
  336. }
  337. }
  338. #endregion
  339.  
  340. /// <summary>
  341. /// 功能描述:获取显示个数
  342. /// 作  者:HZH
  343. /// 创建日期:2019-03-05 10:02:58
  344. /// 任务编号:POS
  345. /// </summary>
  346. /// <returns>返回值</returns>
  347. private void ResetShowCount()
  348. {
  349. if (DesignMode)
  350. { return; }
  351. ShowCount = this.panRow.Height / (m_rowHeight);
  352. int intCha = this.panRow.Height % (m_rowHeight);
  353. m_rowHeight += intCha / ShowCount;
  354. }
  355. #endregion
  356.  
  357. #region 公共函数
  358. /// <summary>
  359. /// 刷新数据
  360. /// </summary>
  361. public void ReloadSource()
  362. {
  363. if (DesignMode)
  364. { return; }
  365. try
  366. {
  367. if (m_columns == null || m_columns.Count <= )
  368. return;
  369.  
  370. ControlHelper.FreezeControl(this.panRow, true);
  371. this.panRow.Controls.Clear();
  372. Rows = new List<IDataGridViewRow>();
  373. if (m_dataSource != null)
  374. {
  375. int intIndex = ;
  376. Control lastItem = null;
  377.  
  378. int intSourceCount = ;
  379. if (m_dataSource is DataTable)
  380. {
  381. intSourceCount = (m_dataSource as DataTable).Rows.Count;
  382. }
  383. else if (typeof(IList).IsAssignableFrom(m_dataSource.GetType()))
  384. {
  385. intSourceCount = (m_dataSource as IList).Count;
  386. }
  387.  
  388. foreach (Control item in this.panRow.Controls)
  389. {
  390.  
  391. if (intIndex >= intSourceCount)
  392. {
  393. item.Visible = false;
  394. }
  395. else
  396. {
  397. var row = (item as IDataGridViewRow);
  398. row.IsShowCheckBox = m_isShowCheckBox;
  399. if (m_dataSource is DataTable)
  400. {
  401. row.DataSource = (m_dataSource as DataTable).Rows[intIndex];
  402. }
  403. else
  404. {
  405. row.DataSource = (m_dataSource as IList)[intIndex];
  406. }
  407. row.BindingCellData();
  408. item.Height = m_rowHeight;
  409. item.Visible = true;
  410. item.BringToFront();
  411. if (lastItem == null)
  412. lastItem = item;
  413. Rows.Add(row);
  414. }
  415. intIndex++;
  416. }
  417.  
  418. if (intIndex < intSourceCount)
  419. {
  420. for (int i = intIndex; i < intSourceCount; i++)
  421. {
  422. IDataGridViewRow row = (IDataGridViewRow)Activator.CreateInstance(m_rowType);
  423. if (m_dataSource is DataTable)
  424. {
  425. row.DataSource = (m_dataSource as DataTable).Rows[i];
  426. }
  427. else
  428. {
  429. row.DataSource = (m_dataSource as IList)[i];
  430. }
  431. row.Columns = m_columns;
  432. List<Control> lstCells = new List<Control>();
  433. row.IsShowCheckBox = m_isShowCheckBox;
  434. row.ReloadCells();
  435. row.BindingCellData();
  436.  
  437. Control rowControl = (row as Control);
  438. rowControl.Height = m_rowHeight;
  439. this.panRow.Controls.Add(rowControl);
  440. rowControl.Dock = DockStyle.Top;
  441. row.CellClick += (a, b) => { SetSelectRow(rowControl, b); };
  442. row.CheckBoxChangeEvent += (a, b) => { SetSelectRow(rowControl, b); };
  443. row.SourceChanged += RowSourceChanged;
  444. rowControl.BringToFront();
  445. Rows.Add(row);
  446.  
  447. if (lastItem == null)
  448. lastItem = rowControl;
  449. }
  450. }
  451. if (lastItem != null && intSourceCount == m_showCount)
  452. {
  453. lastItem.Height = this.panRow.Height - (m_showCount - ) * m_rowHeight;
  454. }
  455. }
  456. }
  457. finally
  458. {
  459. ControlHelper.FreezeControl(this.panRow, false);
  460. }
  461. }
  462.  
  463. /// <summary>
  464. /// 快捷键
  465. /// </summary>
  466. /// <param name="msg"></param>
  467. /// <param name="keyData"></param>
  468. /// <returns></returns>
  469. protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
  470. {
  471. if (keyData == Keys.Up)
  472. {
  473. Previous();
  474. }
  475. else if (keyData == Keys.Down)
  476. {
  477. Next();
  478. }
  479. else if (keyData == Keys.Home)
  480. {
  481. First();
  482. }
  483. else if (keyData == Keys.End)
  484. {
  485. End();
  486. }
  487. return base.ProcessCmdKey(ref msg, keyData);
  488. }
  489. /// <summary>
  490. /// 选中第一个
  491. /// </summary>
  492. public void First()
  493. {
  494. if (Rows == null || Rows.Count <= )
  495. return;
  496. Control c = null;
  497. c = (Rows[] as Control);
  498. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = });
  499. }
  500. /// <summary>
  501. /// 选中上一个
  502. /// </summary>
  503. public void Previous()
  504. {
  505. if (Rows == null || Rows.Count <= )
  506. return;
  507. Control c = null;
  508.  
  509. int index = Rows.IndexOf(m_selectRow);
  510. if (index - >= )
  511. {
  512. c = (Rows[index - ] as Control);
  513. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = index - });
  514. }
  515. }
  516. /// <summary>
  517. /// 选中下一个
  518. /// </summary>
  519. public void Next()
  520. {
  521. if (Rows == null || Rows.Count <= )
  522. return;
  523. Control c = null;
  524.  
  525. int index = Rows.IndexOf(m_selectRow);
  526. if (index + < Rows.Count)
  527. {
  528. c = (Rows[index + ] as Control);
  529. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = index + });
  530. }
  531. }
  532. /// <summary>
  533. /// 选中最后一个
  534. /// </summary>
  535. public void End()
  536. {
  537. if (Rows == null || Rows.Count <= )
  538. return;
  539. Control c = null;
  540. c = (Rows[Rows.Count - ] as Control);
  541. SetSelectRow(c, new DataGridViewEventArgs() { RowIndex = Rows.Count - });
  542. }
  543.  
  544. #endregion
  545.  
  546. #region 事件
  547. void RowSourceChanged(object sender, DataGridViewEventArgs e)
  548. {
  549. if (SourceChanged != null)
  550. SourceChanged(sender, e);
  551. }
  552. private void SetSelectRow(Control item, DataGridViewEventArgs e)
  553. {
  554. try
  555. {
  556. ControlHelper.FreezeControl(this, true);
  557. if (item == null)
  558. return;
  559. if (item.Visible == false)
  560. return;
  561. this.FindForm().ActiveControl = this;
  562. this.FindForm().ActiveControl = item;
  563. if (m_selectRow != null)
  564. {
  565. if (m_selectRow == item)
  566. return;
  567. m_selectRow.SetSelect(false);
  568. }
  569. m_selectRow = item as IDataGridViewRow;
  570. m_selectRow.SetSelect(true);
  571. if (ItemClick != null)
  572. {
  573. ItemClick(item, e);
  574. }
  575. if (this.panRow.Controls.Count > )
  576. {
  577. if (item.Location.Y < )
  578. {
  579. this.panRow.AutoScrollPosition = new Point(, Math.Abs(this.panRow.Controls[this.panRow.Controls.Count - ].Location.Y) + item.Location.Y);
  580. }
  581. else if (item.Location.Y + m_rowHeight > this.panRow.Height)
  582. {
  583. this.panRow.AutoScrollPosition = new Point(, Math.Abs(this.panRow.AutoScrollPosition.Y) + item.Location.Y - this.panRow.Height + m_rowHeight);
  584. }
  585. }
  586. }
  587. finally
  588. {
  589. ControlHelper.FreezeControl(this, false);
  590. }
  591. }
  592. private void UCDataGridView_Resize(object sender, EventArgs e)
  593. {
  594. ResetShowCount();
  595. ReloadSource();
  596. }
  597. #endregion
  598. }
  599. }
  1. namespace HZH_Controls.Controls
  2. {
  3. partial class UCDataGridView
  4. {
  5. /// <summary>
  6. /// 必需的设计器变量。
  7. /// </summary>
  8. private System.ComponentModel.IContainer components = null;
  9.  
  10. /// <summary>
  11. /// 清理所有正在使用的资源。
  12. /// </summary>
  13. /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
  14. protected override void Dispose(bool disposing)
  15. {
  16. if (disposing && (components != null))
  17. {
  18. components.Dispose();
  19. }
  20. base.Dispose(disposing);
  21. }
  22.  
  23. #region 组件设计器生成的代码
  24.  
  25. /// <summary>
  26. /// 设计器支持所需的方法 - 不要
  27. /// 使用代码编辑器修改此方法的内容。
  28. /// </summary>
  29. private void InitializeComponent()
  30. {
  31. this.panHead = new System.Windows.Forms.Panel();
  32. this.panColumns = new System.Windows.Forms.TableLayoutPanel();
  33. this.ucSplitLine_H1 = new HZH_Controls.Controls.UCSplitLine_H();
  34. this.panRow = new System.Windows.Forms.Panel();
  35. this.panPage = new System.Windows.Forms.Panel();
  36. this.panHead.SuspendLayout();
  37. this.SuspendLayout();
  38. //
  39. // panHead
  40. //
  41. this.panHead.Controls.Add(this.panColumns);
  42. this.panHead.Controls.Add(this.ucSplitLine_H1);
  43. this.panHead.Dock = System.Windows.Forms.DockStyle.Top;
  44. this.panHead.Location = new System.Drawing.Point(, );
  45. this.panHead.Name = "panHead";
  46. this.panHead.Size = new System.Drawing.Size(, );
  47. this.panHead.TabIndex = ;
  48. //
  49. // panColumns
  50. //
  51. this.panColumns.ColumnCount = ;
  52. this.panColumns.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
  53. this.panColumns.Dock = System.Windows.Forms.DockStyle.Fill;
  54. this.panColumns.Location = new System.Drawing.Point(, );
  55. this.panColumns.Name = "panColumns";
  56. this.panColumns.RowCount = ;
  57. this.panColumns.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
  58. this.panColumns.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
  59. this.panColumns.Size = new System.Drawing.Size(, );
  60. this.panColumns.TabIndex = ;
  61. //
  62. // ucSplitLine_H1
  63. //
  64. this.ucSplitLine_H1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)()))), ((int)(((byte)()))), ((int)(((byte)()))));
  65. this.ucSplitLine_H1.Dock = System.Windows.Forms.DockStyle.Bottom;
  66. this.ucSplitLine_H1.Location = new System.Drawing.Point(, );
  67. this.ucSplitLine_H1.Name = "ucSplitLine_H1";
  68. this.ucSplitLine_H1.Size = new System.Drawing.Size(, );
  69. this.ucSplitLine_H1.TabIndex = ;
  70. this.ucSplitLine_H1.TabStop = false;
  71. //
  72. // panRow
  73. //
  74. this.panRow.AutoScroll = true;
  75. this.panRow.Dock = System.Windows.Forms.DockStyle.Fill;
  76. this.panRow.Location = new System.Drawing.Point(, );
  77. this.panRow.Name = "panRow";
  78. this.panRow.Size = new System.Drawing.Size(, );
  79. this.panRow.TabIndex = ;
  80. //
  81. // panPage
  82. //
  83. this.panPage.Dock = System.Windows.Forms.DockStyle.Bottom;
  84. this.panPage.Location = new System.Drawing.Point(, );
  85. this.panPage.Name = "panPage";
  86. this.panPage.Size = new System.Drawing.Size(, );
  87. this.panPage.TabIndex = ;
  88. this.panPage.Visible = false;
  89. //
  90. // UCDataGridView
  91. //
  92. this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
  93. this.BackColor = System.Drawing.Color.White;
  94. this.Controls.Add(this.panRow);
  95. this.Controls.Add(this.panPage);
  96. this.Controls.Add(this.panHead);
  97. this.Name = "UCDataGridView";
  98. this.Size = new System.Drawing.Size(, );
  99. this.Resize += new System.EventHandler(this.UCDataGridView_Resize);
  100. this.panHead.ResumeLayout(false);
  101. this.ResumeLayout(false);
  102.  
  103. }
  104.  
  105. #endregion
  106.  
  107. private System.Windows.Forms.Panel panHead;
  108. private System.Windows.Forms.TableLayoutPanel panColumns;
  109. private UCSplitLine_H ucSplitLine_H1;
  110. private System.Windows.Forms.Panel panRow;
  111. private System.Windows.Forms.Panel panPage;
  112.  
  113. }
  114. }

如果你仔细看,你会发现行我用了类型进行传入,当你需要更丰富的行内容的时候,可以自定义行控件,然后通过RowType属性传入

分页控件我使用了分页控件基类UCPagerControlBase,这样做的好处就是你同样可以扩展分页控件

用处及效果

调用示例

  1. List<DataGridViewColumnEntity> lstCulumns = new List<DataGridViewColumnEntity>();
  2. lstCulumns.Add(new DataGridViewColumnEntity() { DataField = "ID", HeadText = "编号", Width = , WidthType = SizeType.Absolute });
  3. lstCulumns.Add(new DataGridViewColumnEntity() { DataField = "Name", HeadText = "姓名", Width = , WidthType = SizeType.Percent });
  4. lstCulumns.Add(new DataGridViewColumnEntity() { DataField = "Age", HeadText = "年龄", Width = , WidthType = SizeType.Percent });
  5. lstCulumns.Add(new DataGridViewColumnEntity() { DataField = "Birthday", HeadText = "生日", Width = , WidthType = SizeType.Percent, Format = (a) => { return ((DateTime)a).ToString("yyyy-MM-dd"); } });
  6. lstCulumns.Add(new DataGridViewColumnEntity() { DataField = "Sex", HeadText = "性别", Width = , WidthType = SizeType.Percent, Format = (a) => { return ((int)a) == ? "女" : "男"; } });
  7. this.ucDataGridView1.Columns = lstCulumns;
  8. this.ucDataGridView1.IsShowCheckBox = true;
  9. List<object> lstSource = new List<object>();
  10. for (int i = ; i < ; i++)
  11. {
  12. TestModel model = new TestModel()
  13. {
  14. ID = i.ToString(),
  15. Age = * i,
  16. Name = "姓名——" + i,
  17. Birthday = DateTime.Now.AddYears(-),
  18. Sex = i %
  19. };
  20. lstSource.Add(model);
  21. }
  22.  
  23. var page = new UCPagerControl2();
  24. page.DataSource = lstSource;
  25. this.ucDataGridView1.Page = page;
  26. this.ucDataGridView1.First();

如果使用分页控件,则将数据源指定给分页控件,否则直接指定给表格控件数据源

最后的话

如果你喜欢的话,请到 https://gitee.com/kwwwvagaa/net_winform_custom_control 点个星 星吧

(三十二)c#Winform自定义控件-表格的更多相关文章

  1. (三十)c#Winform自定义控件-文本框(三)

    前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...

  2. Java开发笔记(一百三十二)Swing的表格

    前面介绍了程序界面上一些简单控件的组合排列,它们用来表达相互之间联系较弱的信息倒还凑合,要是用来表达关联性较强的聚合信息就力不从心了.倘若只是简单信息的罗列,例如商品名称列表.新闻标题列表.学生姓名列 ...

  3. (八十六)c#Winform自定义控件-表格优化

    出处:http://www.hzhcontrols.com/原文:http://www.hzhcontrols.com/blog-149.html本文版权归www.hzhcontrols.com所有欢 ...

  4. Bootstrap <基础三十二>模态框(Modal)插件

    模态框(Modal)是覆盖在父窗体上的子窗体.通常,目的是显示来自一个单独的源的内容,可以在不离开父窗体的情况下有一些互动.子窗体可提供信息.交互等. 如果您想要单独引用该插件的功能,那么您需要引用  ...

  5. COJ968 WZJ的数据结构(负三十二)

    WZJ的数据结构(负三十二) 难度级别:D: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,边上均有权值,每个点上有 ...

  6. NeHe OpenGL教程 第三十二课:拾取游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  7. 三十二、Java图形化界面设计——布局管理器之CardLayout(卡片布局)

    摘自 http://blog.csdn.net/liujun13579/article/details/7773945 三十二.Java图形化界面设计--布局管理器之CardLayout(卡片布局) ...

  8. JAVA之旅(三十二)——JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用

    JAVA之旅(三十二)--JAVA网络请求,IP地址,TCP/UDP通讯协议概述,Socket,UDP传输,多线程UDP聊天应用 GUI写到一半电脑系统挂了,也就算了,最多GUI还有一个提示框和实例, ...

  9. Java进阶(三十二) HttpClient使用详解

    Java进阶(三十二) HttpClient使用详解 Http协议的重要性相信不用我多说了,HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性(具体区别,日后我们 ...

  10. Gradle 1.12用户指南翻译——第三十二章. JDepend 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

随机推荐

  1. 项目中操作redis改brpop阻塞模式为订阅模式的实现-java实习笔记二

    更改项目需求以及项目之前阻塞模式问题的叙述已经在上一篇说过了,详情可参考:https://www.cnblogs.com/darope/p/10276213.html  ,https://yq.ali ...

  2. GLFW+GLEW搭建opengl环境(备忘)

    使用VS2017社区版本(免费版) 下载GLFW和GLEW源码. 使用CMAKE生成工程文件 打开右击GLFW和GLEW项目编译 GLFW默认是静态库 编译GLEW时调整为静态库.将生成的lib和源码 ...

  3. deque双端队列笔记

    clear()clear()clear():清空队列 pushpushpush_back()back()back():从尾部插入一个元素. pushpushpush_front()front()fro ...

  4. CentOS 7.3 配置静态ip

    镜像:CentOS-7-x86_64-DVD-1511.iso 1.修改.查看虚拟机的网段 1.1.查看虚拟机网段 编辑-> 虚拟机网络编辑器,修改的需要管理员权限 选择NAT模式 点击 NAT ...

  5. C#中用WMI实现对驱动的查询

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. 【Java中级】(四)多线程

    线程的概念 进程和线程的主要差别在于它们是不同的操作系统资源管理方式.进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径.线程有自己的堆栈和局 ...

  7. PHP 跨域处理

    PHP 跨域处理 跨域访问失败是会出现 No 'Access-Control-Allow-Origin' header is present on the requested resource. Or ...

  8. java并发笔记之java线程模型

    警告⚠️:本文耗时很长,先做好心理准备 java当中的线程和操作系统的线程是什么关系? 猜想: java thread —-对应-—> OS thread Linux关于操作系统的线程控制源码: ...

  9. Apache SSI 远程命令执行漏洞复现

    Apache SSI 远程命令执行漏洞复现 一.漏洞描述 当目标服务器开启了SSI与CGI支持,我们就可以上传shtml,利用<!--#exec cmd=”id” -->语法执行命令. 使 ...

  10. 第三章 jsp数据交互(二)

    Application:当前服务器(可以包含多个会话):当服务器启动后就会创建一个application对象,被所有用户共享page.request.session.application四个作用域对 ...