MDataGridView.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Collections;
  6. using System.ComponentModel;
  7. using System.Windows.Forms;
  8. using System.Drawing;
  9. using System.Drawing.Design;
  10. using System.Diagnostics;
  11. namespace JDFShowSystem
  12. {
  13. public partial class MDataGridView : DataGridView
  14. {
  15. private TreeView[] _columnTreeView;
  16. private ArrayList _columnList = new ArrayList();
  17. private int _cellHeight = 17;
  18. public int CellHeight
  19. {
  20. get { return _cellHeight; }
  21. set { _cellHeight = value; }
  22. }
  23. private int _columnDeep = 1;
  24. private bool HscrollRefresh = false;
  25. /// <summary>
  26. /// 水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误
  27. /// </summary>
  28. [Description("水平滚动时是否刷新表头,数据较多时可能会闪烁,不刷新时可能显示错误")]
  29. public bool RefreshAtHscroll
  30. {
  31. get { return HscrollRefresh; }
  32. set { HscrollRefresh = value; }
  33. }
  34. /// <summary>
  35. /// 构造函数
  36. /// </summary>
  37. public MDataGridView()
  38. {
  39. InitializeComponent();
  40. this.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;
  41. //设置列高度显示模式
  42. }
  43. public MDataGridView(IContainer container)
  44. {
  45. container.Add(this);
  46. InitializeComponent();
  47. }
  48. [Description("设置或获得合并表头树的深度")]
  49. public int ColumnDeep
  50. {
  51. get
  52. {
  53. if (this.Columns.Count == 0)
  54. _columnDeep = 1;
  55. this.ColumnHeadersHeight = _cellHeight * _columnDeep;
  56. return _columnDeep;
  57. }
  58. set
  59. {
  60. if (value < 1)
  61. _columnDeep = 1;
  62. else
  63. _columnDeep = value;
  64. this.ColumnHeadersHeight = _cellHeight * _columnDeep;
  65. }
  66. }
  67. [Description("添加合并式单元格绘制的所需要的节点对象")]
  68. public TreeView[] ColumnTreeView
  69. {
  70. get { return _columnTreeView; }
  71. set
  72. {
  73. if (_columnTreeView != null)
  74. {
  75. for (int i = 0; i <= _columnTreeView.Length - 1; i++)
  76. _columnTreeView[i].Dispose();
  77. }
  78. _columnTreeView = value;
  79. }
  80. }
  81. [Description("设置添加的字段树的相关属性")]
  82. public TreeView ColumnTreeViewNode
  83. {
  84. get { return _columnTreeView[0]; }
  85. }
  86. /// <summary>
  87. /// 设置或获取合并列的集合
  88. /// </summary>
  89. [MergableProperty(false)]
  90. [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
  91. [DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
  92. [Localizable(true)]
  93. [Description("设置或获取合并列的集合"), Browsable(true), Category("单元格合并")]
  94. public List<string> MergeColumnNames
  95. {
  96. get
  97. {
  98. return _mergecolumnname;
  99. }
  100. set
  101. {
  102. _mergecolumnname = value;
  103. }
  104. }
  105. private List<string> _mergecolumnname = new List<string>();
  106. public ArrayList NadirColumnList
  107. {
  108. get
  109. {
  110. if (_columnTreeView == null)
  111. return null;
  112. if (_columnTreeView[0] == null)
  113. return null;
  114. if (_columnTreeView[0].Nodes == null)
  115. return null;
  116. if (_columnTreeView[0].Nodes.Count == 0)
  117. return null;
  118. _columnList.Clear();
  119. GetNadirColumnNodes(_columnList, _columnTreeView[0].Nodes[0], false);
  120. return _columnList;
  121. }
  122. }
  123. ///<summary>
  124. ///绘制合并表头
  125. ///</summary>
  126. ///<param name="node">合并表头节点</param>
  127. ///<param name="e">绘图参数集</param>
  128. ///<param name="level">结点深度</param>
  129. ///<remarks></remarks>
  130. public void PaintUnitHeader(
  131. TreeNode node,
  132. System.Windows.Forms.DataGridViewCellPaintingEventArgs e,
  133. int level)
  134. {
  135. //根节点时退出递归调用
  136. if (level == 0)
  137. return;
  138. RectangleF uhRectangle;
  139. int uhWidth;
  140. SolidBrush gridBrush = new SolidBrush(this.GridColor);
  141. SolidBrush backColorBrush = new SolidBrush(e.CellStyle.BackColor);
  142. Pen gridLinePen = new Pen(gridBrush);
  143. StringFormat textFormat = new StringFormat();
  144. textFormat.Alignment = StringAlignment.Center;
  145. uhWidth = GetUnitHeaderWidth(node);
  146. if (node.Nodes.Count == 0)
  147. {
  148. uhRectangle = new Rectangle(e.CellBounds.Left,
  149. e.CellBounds.Top + node.Level * _cellHeight,
  150. uhWidth - 1,
  151. _cellHeight * (_columnDeep - node.Level) - 1);
  152. }
  153. else
  154. {
  155. uhRectangle = new Rectangle(
  156. e.CellBounds.Left,
  157. e.CellBounds.Top + node.Level * _cellHeight,
  158. uhWidth - 1,
  159. _cellHeight - 1);
  160. }
  161. //画矩形
  162. e.Graphics.FillRectangle(backColorBrush, uhRectangle);
  163. //划底线
  164. e.Graphics.DrawLine(gridLinePen
  165. , uhRectangle.Left
  166. , uhRectangle.Bottom
  167. , uhRectangle.Right
  168. , uhRectangle.Bottom);
  169. //划右端线
  170. e.Graphics.DrawLine(gridLinePen
  171. , uhRectangle.Right
  172. , uhRectangle.Top
  173. , uhRectangle.Right
  174. , uhRectangle.Bottom);
  175. ////写字段文本
  176. e.Graphics.DrawString(node.Text, this.Font
  177. , new SolidBrush(e.CellStyle.ForeColor)
  178. , uhRectangle.Left + uhRectangle.Width / 2 -
  179. e.Graphics.MeasureString(node.Text, this.Font).Width / 2 - 1
  180. , uhRectangle.Top +
  181. uhRectangle.Height / 2 - e.Graphics.MeasureString(node.Text, this.Font).Height / 2);
  182. //递归调用()
  183. if (node.PrevNode == null)
  184. if (node.Parent != null)
  185. PaintUnitHeader(node.Parent, e, level - 1);
  186. }
  187. /// <summary>
  188. /// 获得合并标题字段的宽度
  189. /// </summary>
  190. /// <param name="node">字段节点</param>
  191. /// <returns>字段宽度</returns>
  192. /// <remarks></remarks>
  193. private int GetUnitHeaderWidth(TreeNode node)
  194. {
  195. //获得非最底层字段的宽度
  196. int uhWidth = 0;
  197. //获得最底层字段的宽度
  198. if (node.Nodes == null)
  199. return this.Columns[GetColumnListNodeIndex(node)].Width;
  200. if (node.Nodes.Count == 0)
  201. return this.Columns[GetColumnListNodeIndex(node)].Width;
  202. for (int i = 0; i <= node.Nodes.Count - 1; i++)
  203. {
  204. uhWidth = uhWidth + GetUnitHeaderWidth(node.Nodes[i]);
  205. }
  206. return uhWidth;
  207. }
  208. /// <summary>
  209. /// 获得底层字段索引
  210. /// </summary>
  211. ///' <param name="node">底层字段节点</param>
  212. /// <returns>索引</returns>
  213. /// <remarks></remarks>
  214. private int GetColumnListNodeIndex(TreeNode node)
  215. {
  216. for (int i = 0; i <= _columnList.Count - 1; i++)
  217. {
  218. if (((TreeNode)_columnList[i]).Equals(node))
  219. return i;
  220. }
  221. return -1;
  222. }
  223. /// <summary>
  224. /// 获得底层字段集合
  225. /// </summary>
  226. /// <param name="alList">底层字段集合</param>
  227. /// <param name="node">字段节点</param>
  228. /// <param name="checked">向上搜索与否</param>
  229. /// <remarks></remarks>
  230. private void GetNadirColumnNodes(
  231. ArrayList alList,
  232. TreeNode node,
  233. Boolean isChecked)
  234. {
  235. if (isChecked == false)
  236. {
  237. if (node.FirstNode == null)
  238. {
  239. alList.Add(node);
  240. if (node.NextNode != null)
  241. {
  242. GetNadirColumnNodes(alList, node.NextNode, false);
  243. return;
  244. }
  245. if (node.Parent != null)
  246. {
  247. GetNadirColumnNodes(alList, node.Parent, true);
  248. return;
  249. }
  250. }
  251. else
  252. {
  253. if (node.FirstNode != null)
  254. {
  255. GetNadirColumnNodes(alList, node.FirstNode, false);
  256. return;
  257. }
  258. }
  259. }
  260. else
  261. {
  262. if (node.FirstNode == null)
  263. {
  264. return;
  265. }
  266. else
  267. {
  268. if (node.NextNode != null)
  269. {
  270. GetNadirColumnNodes(alList, node.NextNode, false);
  271. return;
  272. }
  273. if (node.Parent != null)
  274. {
  275. GetNadirColumnNodes(alList, node.Parent, true);
  276. return;
  277. }
  278. }
  279. }
  280. }
  281. /// <summary>
  282. /// 滚动
  283. /// </summary>
  284. /// <param name="e"></param>
  285. protected override void OnScroll(ScrollEventArgs e)
  286. {
  287. bool scrollDirection = (e.ScrollOrientation == ScrollOrientation.HorizontalScroll);
  288. base.OnScroll(e);
  289. if (RefreshAtHscroll && scrollDirection)
  290. this.Refresh();
  291. }
  292. /// <summary>
  293. /// 列宽度改变的重写
  294. /// </summary>
  295. /// <param name="e"></param>
  296. protected override void OnColumnWidthChanged(DataGridViewColumnEventArgs e)
  297. {
  298. Graphics g = Graphics.FromHwnd(this.Handle);
  299. try
  300. {
  301. float uwh = g.MeasureString(e.Column.HeaderText, this.Font).Width;
  302. if (uwh >= e.Column.Width) { e.Column.Width = Convert.ToInt16(uwh); }
  303. base.OnColumnWidthChanged(e);
  304. }
  305. catch
  306. { }
  307. }
  308. /// <summary>
  309. /// 单元格绘制(重写)
  310. /// </summary>
  311. /// <param name="e"></param>
  312. /// <remarks></remarks>
  313. protected override void OnCellPainting(System.Windows.Forms.DataGridViewCellPaintingEventArgs e)
  314. {
  315. try
  316. {
  317. if (e.RowIndex > -1 && e.ColumnIndex > -1)
  318. {
  319. DrawCell(e);
  320. }
  321. else
  322. {
  323. //行标题不重写
  324. if (e.ColumnIndex < 0)
  325. {
  326. base.OnCellPainting(e);
  327. return;
  328. }
  329. if (_columnDeep == 1)
  330. {
  331. base.OnCellPainting(e);
  332. return;
  333. }
  334. //绘制表头
  335. if (e.RowIndex == -1)
  336. {
  337. if (e.ColumnIndex >= NadirColumnList.Count) { e.Handled = true; return; }
  338. PaintUnitHeader((TreeNode)NadirColumnList[e.ColumnIndex]
  339. , e
  340. , _columnDeep);
  341. e.Handled = true;
  342. }
  343. }
  344. }
  345. catch
  346. { }
  347. }
  348. #region 合并单元格
  349. /// <summary>
  350. /// 画单元格
  351. /// </summary>
  352. /// <param name="e"></param>
  353. private void DrawCell(DataGridViewCellPaintingEventArgs e)
  354. {
  355. if (e.CellStyle.Alignment == DataGridViewContentAlignment.NotSet)
  356. {
  357. e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
  358. }
  359. Brush gridBrush = new SolidBrush(this.GridColor);
  360. SolidBrush backBrush = new SolidBrush(e.CellStyle.BackColor);
  361. SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
  362. int cellwidth;
  363. //上面相同的行数
  364. int UpRows = 0;
  365. //下面相同的行数
  366. int DownRows = 0;
  367. //总行数
  368. int count = 0;
  369. if (this.MergeColumnNames.Contains(this.Columns[e.ColumnIndex].Name) && e.RowIndex != -1)
  370. {
  371. cellwidth = e.CellBounds.Width;
  372. Pen gridLinePen = new Pen(gridBrush);
  373. string curValue = e.Value == null ? "" : e.Value.ToString().Trim();
  374. string curSelected = this.CurrentRow.Cells[e.ColumnIndex].Value == null ? "" : this.CurrentRow.Cells[e.ColumnIndex].Value.ToString().Trim();
  375. if (!string.IsNullOrEmpty(curValue))
  376. {
  377. #region 获取下面的行数
  378. for (int i = e.RowIndex; i < this.Rows.Count; i++)
  379. {
  380. if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
  381. {
  382. //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
  383. DownRows++;
  384. if (e.RowIndex != i)
  385. {
  386. cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
  387. }
  388. }
  389. else
  390. {
  391. break;
  392. }
  393. }
  394. #endregion
  395. #region 获取上面的行数
  396. for (int i = e.RowIndex; i >= 0; i--)
  397. {
  398. if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
  399. {
  400. //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
  401. UpRows++;
  402. if (e.RowIndex != i)
  403. {
  404. cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
  405. }
  406. }
  407. else
  408. {
  409. break;
  410. }
  411. }
  412. #endregion
  413. count = DownRows + UpRows - 1;
  414. if (count < 2)
  415. {
  416. return;
  417. }
  418. }
  419. if (this.Rows[e.RowIndex].Selected)
  420. {
  421. backBrush.Color = e.CellStyle.SelectionBackColor;
  422. fontBrush.Color = e.CellStyle.SelectionForeColor;
  423. }
  424. //以背景色填充
  425. e.Graphics.FillRectangle(backBrush, e.CellBounds);
  426. //画字符串
  427. PaintingFont(e, cellwidth, UpRows, DownRows, count);
  428. if (DownRows == 1)
  429. {
  430. e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
  431. count = 0;
  432. }
  433. // 画右边线
  434. e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom);
  435. e.Handled = true;
  436. }
  437. }
  438. /// <summary>
  439. /// 画字符串
  440. /// </summary>
  441. /// <param name="e"></param>
  442. /// <param name="cellwidth"></param>
  443. /// <param name="UpRows"></param>
  444. /// <param name="DownRows"></param>
  445. /// <param name="count"></param>
  446. private void PaintingFont(System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int cellwidth, int UpRows, int DownRows, int count)
  447. {
  448. SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
  449. int fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
  450. int fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
  451. int cellheight = e.CellBounds.Height;
  452. if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomCenter)
  453. {
  454. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y + cellheight * DownRows - fontheight);
  455. }
  456. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomLeft)
  457. {
  458. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y + cellheight * DownRows - fontheight);
  459. }
  460. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomRight)
  461. {
  462. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y + cellheight * DownRows - fontheight);
  463. }
  464. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleCenter)
  465. {
  466. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
  467. }
  468. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleLeft)
  469. {
  470. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
  471. }
  472. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleRight)
  473. {
  474. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
  475. }
  476. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopCenter)
  477. {
  478. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1));
  479. }
  480. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopLeft)
  481. {
  482. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1));
  483. }
  484. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopRight)
  485. {
  486. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1));
  487. }
  488. else
  489. {
  490. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
  491. }
  492. }
  493. #endregion
  494. }
  495. }