OTSGridView.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Drawing.Design;
  6. using System.Windows.Forms;
  7. /// <summary>
  8. /// DataGridView行合并.请对属性MergeColumnNames 赋值既可
  9. /// </summary>
  10. public partial class OTSGridView : DataGridView
  11. {
  12. #region 构造函数
  13. public OTSGridView()
  14. {
  15. InitializeComponent();
  16. }
  17. #endregion
  18. #region 重写的事件
  19. protected override void OnScroll(ScrollEventArgs e)
  20. {
  21. //为了帮助OTSGridView表头不能自动刷新,所以在这里判断水平方向移动时,刷新Grid
  22. if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
  23. {
  24. this.Refresh();
  25. }
  26. base.OnScroll(e);
  27. }
  28. protected override void OnPaint(PaintEventArgs pe)
  29. {
  30. // TODO: 在此处添加自定义绘制代码
  31. // 调用基类 OnPaint
  32. base.OnPaint(pe);
  33. }
  34. protected override void OnCellPainting(DataGridViewCellPaintingEventArgs e)
  35. {
  36. try
  37. {
  38. if (e.RowIndex > -1 && e.ColumnIndex > -1)
  39. {
  40. DrawCell(e);
  41. }
  42. else
  43. {
  44. //二维表头
  45. if (e.RowIndex == -1)
  46. {
  47. if (SpanRows.ContainsKey(e.ColumnIndex)) //被合并的列
  48. {
  49. //画边框
  50. Graphics g = e.Graphics;
  51. e.Paint(e.CellBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border);
  52. int left = e.CellBounds.Left, top = e.CellBounds.Top + 2,
  53. right = e.CellBounds.Right, bottom = e.CellBounds.Bottom;
  54. switch (SpanRows[e.ColumnIndex].Position)
  55. {
  56. case 1:
  57. left += 2;
  58. break;
  59. case 2:
  60. break;
  61. case 3:
  62. right -= 2;
  63. break;
  64. }
  65. //画上半部分底色
  66. g.FillRectangle(new SolidBrush(this._mergecolumnheaderbackcolor), left, top,
  67. right - left, (bottom - top) / 2);
  68. //画中线
  69. g.DrawLine(new Pen(this.GridColor), left, (top + bottom) / 2,
  70. right, (top + bottom) / 2);
  71. //写小标题
  72. StringFormat sf = new StringFormat();
  73. sf.Alignment = StringAlignment.Center;
  74. sf.LineAlignment = StringAlignment.Center;
  75. g.DrawString(e.Value + "", e.CellStyle.Font, Brushes.Black,
  76. new Rectangle(left, (top + bottom) / 2, right - left, (bottom - top) / 2), sf);
  77. left = this.GetColumnDisplayRectangle(SpanRows[e.ColumnIndex].Left, true).Left - 2;
  78. if (left < 0) left = this.GetCellDisplayRectangle(-1, -1, true).Width;
  79. right = this.GetColumnDisplayRectangle(SpanRows[e.ColumnIndex].Right, true).Right - 2;
  80. if (right < 0) right = this.Width;
  81. g.DrawString(SpanRows[e.ColumnIndex].Text, e.CellStyle.Font, Brushes.Black,
  82. new Rectangle(left, top, right - left, (bottom - top) / 2), sf);
  83. e.Handled = true;
  84. }
  85. }
  86. }
  87. base.OnCellPainting(e);
  88. }
  89. catch
  90. { }
  91. }
  92. protected override void OnCellClick(DataGridViewCellEventArgs e)
  93. {
  94. base.OnCellClick(e);
  95. }
  96. #endregion
  97. #region 自定义方法
  98. /// <summary>
  99. /// 画单元格
  100. /// </summary>
  101. /// <param name="e"></param>
  102. private void DrawCell(DataGridViewCellPaintingEventArgs e)
  103. {
  104. if (e.CellStyle.Alignment == DataGridViewContentAlignment.NotSet)
  105. {
  106. e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
  107. }
  108. Brush gridBrush = new SolidBrush(this.GridColor);
  109. SolidBrush backBrush = new SolidBrush(e.CellStyle.BackColor);
  110. SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
  111. int cellwidth;
  112. //上面相同的行数
  113. int UpRows = 0;
  114. //下面相同的行数
  115. int DownRows = 0;
  116. //总行数
  117. int count = 0;
  118. if (this.MergeColumnNames.Contains(this.Columns[e.ColumnIndex].Name) && e.RowIndex != -1)
  119. {
  120. cellwidth = e.CellBounds.Width;
  121. Pen gridLinePen = new Pen(gridBrush);
  122. string curValue = e.Value == null ? "" : e.Value.ToString().Trim();
  123. string curSelected = this.CurrentRow.Cells[e.ColumnIndex].Value == null ? "" : this.CurrentRow.Cells[e.ColumnIndex].Value.ToString().Trim();
  124. if (!string.IsNullOrEmpty(curValue))
  125. {
  126. #region 获取下面的行数
  127. for (int i = e.RowIndex; i < this.Rows.Count; i++)
  128. {
  129. if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
  130. {
  131. //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
  132. DownRows++;
  133. if (e.RowIndex != i)
  134. {
  135. cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
  136. }
  137. }
  138. else
  139. {
  140. break;
  141. }
  142. }
  143. #endregion
  144. #region 获取上面的行数
  145. for (int i = e.RowIndex; i >= 0; i--)
  146. {
  147. if (this.Rows[i].Cells[e.ColumnIndex].Value.ToString().Equals(curValue))
  148. {
  149. //this.Rows[i].Cells[e.ColumnIndex].Selected = this.Rows[e.RowIndex].Cells[e.ColumnIndex].Selected;
  150. UpRows++;
  151. if (e.RowIndex != i)
  152. {
  153. cellwidth = cellwidth < this.Rows[i].Cells[e.ColumnIndex].Size.Width ? cellwidth : this.Rows[i].Cells[e.ColumnIndex].Size.Width;
  154. }
  155. }
  156. else
  157. {
  158. break;
  159. }
  160. }
  161. #endregion
  162. count = DownRows + UpRows - 1;
  163. if (count < 2)
  164. {
  165. return;
  166. }
  167. }
  168. if (this.Rows[e.RowIndex].Selected)
  169. {
  170. backBrush.Color = e.CellStyle.SelectionBackColor;
  171. fontBrush.Color = e.CellStyle.SelectionForeColor;
  172. }
  173. //以背景色填充
  174. e.Graphics.FillRectangle(backBrush, e.CellBounds);
  175. //画字符串
  176. PaintingFont(e, cellwidth, UpRows, DownRows, count);
  177. if (DownRows == 1)
  178. {
  179. e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1, e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
  180. count = 0;
  181. }
  182. // 画右边线
  183. e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top, e.CellBounds.Right - 1, e.CellBounds.Bottom);
  184. e.Handled = true;
  185. }
  186. }
  187. /// <summary>
  188. /// 画字符串
  189. /// </summary>
  190. /// <param name="e"></param>
  191. /// <param name="cellwidth"></param>
  192. /// <param name="UpRows"></param>
  193. /// <param name="DownRows"></param>
  194. /// <param name="count"></param>
  195. private void PaintingFont(System.Windows.Forms.DataGridViewCellPaintingEventArgs e, int cellwidth, int UpRows, int DownRows, int count)
  196. {
  197. SolidBrush fontBrush = new SolidBrush(e.CellStyle.ForeColor);
  198. int fontheight = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Height;
  199. int fontwidth = (int)e.Graphics.MeasureString(e.Value.ToString(), e.CellStyle.Font).Width;
  200. int cellheight = e.CellBounds.Height;
  201. if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomCenter)
  202. {
  203. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y + cellheight * DownRows - fontheight);
  204. }
  205. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomLeft)
  206. {
  207. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y + cellheight * DownRows - fontheight);
  208. }
  209. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.BottomRight)
  210. {
  211. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y + cellheight * DownRows - fontheight);
  212. }
  213. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleCenter)
  214. {
  215. 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);
  216. }
  217. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleLeft)
  218. {
  219. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1) + (cellheight * count - fontheight) / 2);
  220. }
  221. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.MiddleRight)
  222. {
  223. 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);
  224. }
  225. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopCenter)
  226. {
  227. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + (cellwidth - fontwidth) / 2, e.CellBounds.Y - cellheight * (UpRows - 1));
  228. }
  229. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopLeft)
  230. {
  231. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X, e.CellBounds.Y - cellheight * (UpRows - 1));
  232. }
  233. else if (e.CellStyle.Alignment == DataGridViewContentAlignment.TopRight)
  234. {
  235. e.Graphics.DrawString((String)e.Value, e.CellStyle.Font, fontBrush, e.CellBounds.X + cellwidth - fontwidth, e.CellBounds.Y - cellheight * (UpRows - 1));
  236. }
  237. else
  238. {
  239. 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);
  240. }
  241. }
  242. #endregion
  243. #region 属性
  244. /// <summary>
  245. /// 设置或获取合并列的集合
  246. /// </summary>
  247. [MergableProperty(false)]
  248. [Editor("System.Windows.Forms.Design.ListControlStringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
  249. [DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Visible)]
  250. [Localizable(true)]
  251. [Description("设置或获取合并列的集合"), Browsable(true), Category("单元格合并")]
  252. public List<string> MergeColumnNames
  253. {
  254. get
  255. {
  256. return _mergecolumnname;
  257. }
  258. set
  259. {
  260. _mergecolumnname = value;
  261. }
  262. }
  263. private List<string> _mergecolumnname = new List<string>();
  264. #endregion
  265. #region 二维表头
  266. private struct SpanInfo //表头信息
  267. {
  268. public SpanInfo(string Text, int Position, int Left, int Right)
  269. {
  270. this.Text = Text;
  271. this.Position = Position;
  272. this.Left = Left;
  273. this.Right = Right;
  274. }
  275. public string Text; //列主标题
  276. public int Position; //位置,1:左,2中,3右
  277. public int Left; //对应左行
  278. public int Right; //对应右行
  279. }
  280. private Dictionary<int, SpanInfo> SpanRows = new Dictionary<int, SpanInfo>();//需要2维表头的列
  281. /// <summary>
  282. /// 合并列
  283. /// </summary>
  284. /// <param name="ColIndex">列的索引</param>
  285. /// <param name="ColCount">需要合并的列数</param>
  286. /// <param name="Text">合并列后的文本</param>
  287. public void AddSpanHeader(int ColIndex, int ColCount, string Text)
  288. {
  289. if (ColCount < 2)
  290. {
  291. throw new Exception("行宽应大于等于2,合并1列无意义。");
  292. }
  293. //将这些列加入列表
  294. int Right = ColIndex + ColCount - 1; //同一大标题下的最后一列的索引
  295. SpanRows[ColIndex] = new SpanInfo(Text, 1, ColIndex, Right); //添加标题下的最左列
  296. SpanRows[Right] = new SpanInfo(Text, 3, ColIndex, Right); //添加该标题下的最右列
  297. for (int i = ColIndex + 1; i < Right; i++) //中间的列
  298. {
  299. SpanRows[i] = new SpanInfo(Text, 2, ColIndex, Right);
  300. }
  301. }
  302. /// <summary>
  303. /// 清除合并的列
  304. /// </summary>
  305. public void ClearSpanInfo()
  306. {
  307. SpanRows.Clear();
  308. //ReDrawHead();
  309. }
  310. private void DataGridViewEx_Scroll(object sender, ScrollEventArgs e)
  311. {
  312. if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)// && e.Type == ScrollEventType.EndScroll)
  313. {
  314. timer1.Enabled = false; timer1.Enabled = true;
  315. }
  316. }
  317. //刷新显示表头
  318. public void ReDrawHead()
  319. {
  320. foreach (int si in SpanRows.Keys)
  321. {
  322. this.Invalidate(this.GetCellDisplayRectangle(si, -1, true));
  323. }
  324. }
  325. private void timer1_Tick(object sender, EventArgs e)
  326. {
  327. timer1.Enabled = false;
  328. ReDrawHead();
  329. }
  330. /// <summary>
  331. /// 二维表头的背景颜色
  332. /// </summary>
  333. [Description("二维表头的背景颜色"), Browsable(true), Category("二维表头")]
  334. public Color MergeColumnHeaderBackColor
  335. {
  336. get { return this._mergecolumnheaderbackcolor; }
  337. set { this._mergecolumnheaderbackcolor = value; }
  338. }
  339. private Color _mergecolumnheaderbackcolor = System.Drawing.SystemColors.Control;
  340. #endregion
  341. }