GridControlEx.cs 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. using DevExpress.Utils;
  2. using DevExpress.Utils.Helpers;
  3. using DevExpress.Utils.Menu;
  4. using DevExpress.Utils.Paint;
  5. using DevExpress.Utils.Svg;
  6. using DevExpress.XtraBars;
  7. using DevExpress.XtraEditors;
  8. using DevExpress.XtraEditors.Controls;
  9. using DevExpress.XtraEditors.Repository;
  10. using DevExpress.XtraGrid;
  11. using DevExpress.XtraGrid.Columns;
  12. using DevExpress.XtraGrid.Views.Grid;
  13. using DxHelper;
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Drawing;
  17. using System.IO;
  18. using System.Linq;
  19. using System.Text;
  20. using System.Threading.Tasks;
  21. using System.Windows.Forms;
  22. public static class GridControlEx
  23. {
  24. internal class GridTag
  25. {
  26. public GridTag() { }
  27. public PopupMenu PopupMenu { get; set; }
  28. public BarManager BarM { get; set; }
  29. public List<BarButtonItem> RowButtonsItems { get; set; } = new List<BarButtonItem>();
  30. public List<BarButtonItem> MultRowButtonsItems { get; set; } = new List<BarButtonItem>();
  31. }
  32. /// <summary>
  33. /// 初始化表格(默认禁用分组)
  34. /// </summary>
  35. /// <param name="grid"></param>
  36. /// <param name="dataSource">绑定的数据源</param>
  37. /// <param name="rowHeight">行高(默认24px)</param>
  38. /// <param name="showScrollH">是否显示水平滚动条(默认不显示)</param>
  39. /// <typeparam name="T">绑定的数据源模型类型</typeparam>
  40. /// <returns></returns>
  41. public static GridControl UseDefault<T>(this GridControl grid, List<T> dataSource, int rowHeight = 24, bool showScrollH = false)
  42. {
  43. grid.DataSource = dataSource;
  44. grid.MainView.BorderStyle = BorderStyles.Flat;
  45. var view = grid.MainView as GridView;
  46. view.CustomColumnDisplayText += View_CustomColumnDisplayText;
  47. view.Appearance.HeaderPanel.TextOptions.HAlignment = HorzAlignment.Center;
  48. view.Appearance.Row.Options.UseTextOptions = true;
  49. view.Appearance.Row.TextOptions.HAlignment = HorzAlignment.Center;
  50. view.OptionsView.ColumnHeaderAutoHeight = DefaultBoolean.True;
  51. view.RowHeight = rowHeight;
  52. view.OptionsView.ShowGroupPanel = false;
  53. view.OptionsBehavior.Editable = false;
  54. view.OptionsView.ShowDetailButtons = false;
  55. view.OptionsView.ShowIndicator = false;
  56. view.OptionsMenu.EnableColumnMenu = true;
  57. view.OptionsCustomization.AllowFilter = true;
  58. view.OptionsCustomization.AllowGroup = false;
  59. view.OptionsCustomization.AllowSort = true;
  60. view.OptionsCustomization.AllowColumnMoving = true;
  61. view.OptionsCustomization.AllowMergedGrouping = DefaultBoolean.False;
  62. view.OptionsSelection.MultiSelect = false;
  63. view.OptionsCustomization.AllowRowSizing = false;
  64. view.OptionsCustomization.AllowQuickHideColumns = false;
  65. view.OptionsMenu.EnableGroupPanelMenu = false;
  66. view.OptionsMenu.EnableGroupRowMenu = false;
  67. view.OptionsMenu.EnableFooterMenu = false;
  68. view.OptionsLayout.StoreAllOptions = true;
  69. view.OptionsLayout.StoreAppearance = true;
  70. view.OptionsLayout.StoreDataSettings = true;
  71. view.OptionsLayout.StoreVisualOptions = true;
  72. view.OptionsLayout.StoreFormatRules = true;
  73. view.OptionsView.ColumnAutoWidth = !showScrollH;
  74. view.PopupMenuShowing += View_PopupMenuShowing;
  75. view.OptionsSelection.EnableAppearanceFocusedCell = false;
  76. string GetLayoutName()
  77. {
  78. Control ctrl;
  79. if (view.Tag is SearchLookUpEdit searchLookUpEdit)
  80. ctrl = searchLookUpEdit;
  81. else
  82. ctrl = grid;
  83. while (ctrl.Parent != null)
  84. {
  85. ctrl = ctrl.Parent;
  86. if (ctrl is UserControl) break;
  87. }
  88. var props = typeof(T).GetProperties();
  89. StringBuilder sb = new StringBuilder();
  90. foreach (var item in props)
  91. {
  92. sb.Append(item.Name);
  93. }
  94. var md5 = MD5Helper.StrToMD5(sb.ToString());
  95. if (view.Tag is SearchLookUpEdit searchLookUpEdit2)
  96. return $"{ctrl.Name}_{searchLookUpEdit2.Name}_{md5}";
  97. else
  98. return $"{ctrl.Name}_{grid.Name}_{md5}";
  99. }
  100. string name = GetLayoutName();
  101. void SaveLayoutAction()
  102. {
  103. Form frm = null;
  104. if (view.Tag is SearchLookUpEdit edit)
  105. frm = edit.FindForm();
  106. else
  107. frm = grid.FindForm();
  108. if (frm != null)
  109. {
  110. frm.VisibleChanged += (sender2, e2) =>
  111. {
  112. Directory.CreateDirectory("Layout");
  113. if (name == null) return;
  114. grid.MainView?.SaveLayoutToXml($"Layout\\{name}.xml", OptionsLayoutBase.FullLayout);
  115. };
  116. }
  117. }
  118. if (grid.IsLoaded)
  119. {
  120. SaveLayoutAction();
  121. }
  122. else
  123. {
  124. grid.Load += (sender, e) => SaveLayoutAction();
  125. }
  126. if (name != null && File.Exists($"Layout\\{name}.xml"))
  127. {
  128. view.RestoreLayoutFromXml($"Layout\\{name}.xml", OptionsLayoutBase.FullLayout);
  129. view.ClearColumnsFilter();
  130. view.ClearFindFilter();
  131. view.ClearInHeaderSearchText();
  132. view.ClearSorting();
  133. view.ClearSelection();
  134. }
  135. view.KeyUp += View_KeyUp;
  136. grid.Tag = new GridTag();
  137. return grid;
  138. }
  139. /// <summary>
  140. /// 为GirdControl启用右键新增数据的功能
  141. /// </summary>
  142. /// <param name="grid"></param>
  143. /// <param name="emptyText"></param>
  144. /// <returns></returns>
  145. public static GridControl UseEmptyText(this GridControl grid, string emptyText = "暂无数据")
  146. {
  147. if (string.IsNullOrWhiteSpace(emptyText)) return grid;
  148. var view = grid.MainView as GridView;
  149. view.CustomDrawEmptyForeground += (sender, e) =>
  150. {
  151. var s = e.Appearance.CalcTextSize(e.Cache, emptyText, e.Bounds.Width).ToSize();
  152. var x = (e.Bounds.Width - s.Width) / 2;
  153. var y = (e.Bounds.Height - s.Height) / 2;
  154. e.Appearance.ForeColor = Color.Gray;
  155. e.Appearance.DrawString(e.Cache, emptyText, new Rectangle(x, y, s.Width, s.Height));
  156. };
  157. return grid;
  158. }
  159. /// <summary>
  160. /// 为GirdControl启用右键新增数据的功能
  161. /// </summary>
  162. /// <typeparam name="T"></typeparam>
  163. /// <param name="grid"></param>
  164. /// <param name="menuCaption"></param>
  165. /// <param name="callback">一个回调函数,返回新增的数据</param>
  166. /// <returns></returns>
  167. public static GridControl UseAdd<T>(this GridControl grid, Func<T> callback, string menuCaption = "新增")
  168. {
  169. var view = grid.MainView as GridView;
  170. view.CustomDrawEmptyForeground += (sender, e) =>
  171. {
  172. string emptyText = "右键添加";
  173. var s = e.Appearance.CalcTextSize(e.Cache, emptyText, e.Bounds.Width).ToSize();
  174. var x = (e.Bounds.Width - s.Width) / 2;
  175. var y = (e.Bounds.Height - s.Height) / 2;
  176. e.Appearance.ForeColor = Color.Gray;
  177. e.Appearance.DrawString(e.Cache, emptyText, new Rectangle(x, y, s.Width, s.Height));
  178. };
  179. grid.AddContentMenu<T>(menuCaption, DxHelper.SvgHelper.CreateAdd(), data =>
  180. {
  181. if (callback != null)
  182. {
  183. var addRow = callback();
  184. if (addRow == null) return;
  185. var ds = grid.DataSource as List<T>;
  186. ds.Add(addRow);
  187. view.RefreshData();
  188. }
  189. }, true);
  190. return grid;
  191. }
  192. /// <summary>
  193. /// 为GirdControl启用右键新增数据的功能
  194. /// </summary>
  195. /// <typeparam name="T"></typeparam>
  196. /// <param name="grid"></param>
  197. /// <param name="menuCaption"></param>
  198. /// <param name="callback">一个回调函数,返回新增的数据</param>
  199. /// <returns></returns>
  200. public static GridControl UseAddAsync<T>(this GridControl grid, Func<Task<T>> callback, string menuCaption = "新增")
  201. {
  202. grid.AddContentMenuAsync<T>(menuCaption, DxHelper.SvgHelper.CreateAdd(), async data =>
  203. {
  204. if (callback != null)
  205. {
  206. var addRow = await callback();
  207. if (addRow == null) return;
  208. var view = grid.MainView as GridView;
  209. var ds = grid.DataSource as List<T>;
  210. ds.Add(addRow);
  211. view.RefreshData();
  212. }
  213. }, true);
  214. return grid;
  215. }
  216. /// <summary>
  217. /// 为GridControl启用右编辑选中的单行功能
  218. /// </summary>
  219. /// <typeparam name="T"></typeparam>
  220. /// <param name="grid"></param>
  221. /// <param name="menuCaption"></param>
  222. /// <param name="callback"></param>
  223. /// <returns></returns>
  224. public static GridControl UseEdit<T>(this GridControl grid, Func<T, T> callback, string menuCaption = "编辑")
  225. {
  226. grid.AddRowMenu<T>(menuCaption, DxHelper.SvgHelper.CreateEdit(), data =>
  227. {
  228. if (callback != null)
  229. {
  230. var newRow = callback(data);
  231. if (newRow == null) return;
  232. var view = grid.MainView as GridView;
  233. var ds = grid.DataSource as List<T>;
  234. var idx = ds.IndexOf(data);
  235. ds.Remove(data);
  236. ds.Insert(idx, newRow);
  237. view.RefreshData();
  238. }
  239. }, null);
  240. return grid;
  241. }
  242. /// <summary>
  243. /// 为GridControl启用右编辑选中的单行功能
  244. /// </summary>
  245. /// <typeparam name="T"></typeparam>
  246. /// <param name="grid"></param>
  247. /// <param name="menuCaption"></param>
  248. /// <param name="callback"></param>
  249. /// <returns></returns>
  250. public static GridControl UseEditAsync<T>(this GridControl grid, Func<T, Task<T>> callback, string menuCaption = "编辑")
  251. {
  252. grid.AddRowMenu<T>(menuCaption, DxHelper.SvgHelper.CreateEdit(), async data =>
  253. {
  254. if (callback != null)
  255. {
  256. var newRow = await callback(data);
  257. if (newRow == null) return;
  258. var view = grid.MainView as GridView;
  259. var ds = grid.DataSource as List<T>;
  260. var idx = ds.IndexOf(data);
  261. ds.Remove(data);
  262. ds.Insert(idx, newRow);
  263. view.RefreshData();
  264. }
  265. }, null);
  266. return grid;
  267. }
  268. /// <summary>
  269. /// 为GridControl启用右删除选中的一行或多行功能(自动启用UseMultiSelect)
  270. /// </summary>
  271. /// <typeparam name="T"></typeparam>
  272. /// <param name="grid"></param>
  273. /// <param name="menuCaption"></param>
  274. /// <param name="action"></param>
  275. /// <returns></returns>
  276. public static GridControl UseDelete<T>(this GridControl grid, Func<List<T>, bool> action = null, string menuCaption = "删除")
  277. {
  278. grid.AddMultRowMenu<T>(menuCaption, DxHelper.SvgHelper.CreateClose(), data =>
  279. {
  280. if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认删除选中的记录?共[{data.Count}]条")) return;
  281. if (action != null)
  282. {
  283. bool succeed = action(data);
  284. if (!succeed) return;
  285. }
  286. var view = grid.MainView as GridView;
  287. view.DeleteSelectedRows();
  288. view.RefreshData();
  289. });
  290. return grid;
  291. }
  292. /// <summary>
  293. /// 为GridControl启用右删除选中的一行或多行功能(自动启用UseMultiSelect)
  294. /// </summary>
  295. /// <typeparam name="T"></typeparam>
  296. /// <param name="grid"></param>
  297. /// <param name="menuCaption"></param>
  298. /// <param name="action"></param>
  299. /// <returns></returns>
  300. public static GridControl UseDeleteAsync<T>(this GridControl grid, Func<List<T>, Task<bool>> action = null, string menuCaption = "删除")
  301. {
  302. grid.AddMultRowMenu<T>(menuCaption, DxHelper.SvgHelper.CreateClose(), async data =>
  303. {
  304. if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认删除选中的记录?共[{data.Count()}]条")) return;
  305. if (action != null)
  306. {
  307. bool succeed = await action(data);
  308. if (!succeed) return;
  309. }
  310. var view = grid.MainView as GridView;
  311. view.DeleteSelectedRows();
  312. view.RefreshData();
  313. });
  314. return grid;
  315. }
  316. /// <summary>
  317. /// 为GirdControl启用右键清除所有数据的功能
  318. /// </summary>
  319. /// <typeparam name="T"></typeparam>
  320. /// <param name="grid"></param>
  321. /// <param name="menuCaption"></param>
  322. /// <param name="action"></param>
  323. /// <returns></returns>
  324. public static GridControl UseClear<T>(this GridControl grid, Func<List<T>, bool> action = null, string menuCaption = "清除")
  325. {
  326. grid.AddContentMenu<T>(menuCaption, DxHelper.SvgHelper.CreateClear(), data =>
  327. {
  328. if (data == null || data.Count == 0) return;
  329. if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认清空所有记录?共[{data.Count}]条")) return;
  330. if (action != null)
  331. {
  332. bool succeed = action(data);
  333. if (!succeed) return;
  334. }
  335. var view = grid.MainView as GridView;
  336. data.Clear();
  337. view.RefreshData();
  338. }, false);
  339. return grid;
  340. }
  341. public static GridControl SetLogImageColumn(this GridControl grid, string columnFieldName,Type enumType)
  342. {
  343. var view = grid.MainView as GridView;
  344. RepositoryItemImageComboBox edit = new RepositoryItemImageComboBox();
  345. edit.AddEnum(enumType);
  346. SvgImageCollection svgImages = new SvgImageCollection();
  347. svgImages.ImageSize = new System.Drawing.Size(20, 20);
  348. svgImages.Add(SvgHelper.CreateInfo());
  349. svgImages.Add(SvgHelper.CreateWarning());
  350. svgImages.Add(SvgHelper.CreateError());
  351. edit.SmallImages = svgImages;
  352. edit.GlyphAlignment = DevExpress.Utils.HorzAlignment.Center;
  353. view.Columns[columnFieldName].ColumnEdit = edit;
  354. return grid;
  355. }
  356. /// <summary>
  357. /// 为GirdControl启用右键清除所有数据的功能
  358. /// </summary>
  359. /// <typeparam name="T"></typeparam>
  360. /// <param name="grid"></param>
  361. /// <param name="menuCaption"></param>
  362. /// <param name="action"></param>
  363. /// <returns></returns>
  364. public static GridControl UseClearAsync<T>(this GridControl grid, Func<List<T>, Task<bool>> action = null, string menuCaption = "清除")
  365. {
  366. grid.AddContentMenu<T>(menuCaption, DxHelper.SvgHelper.CreateClear(), async data =>
  367. {
  368. if (data == null || data.Count == 0) return;
  369. if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认清空所有记录?共[{data.Count}]条")) return;
  370. if (action != null)
  371. {
  372. bool succeed = await action(data);
  373. if (!succeed) return;
  374. }
  375. var view = grid.MainView as GridView;
  376. data.Clear();
  377. view.RefreshData();
  378. }, false);
  379. return grid;
  380. }
  381. public static GridControl UseExportCsv(this GridControl grid)
  382. {
  383. GridTag tag = grid.Tag as GridTag;
  384. if (tag.BarM == null)
  385. {
  386. tag.BarM = new BarManager();
  387. tag.BarM.Form = grid;
  388. }
  389. if (tag.PopupMenu == null)
  390. {
  391. tag.PopupMenu = new PopupMenu();
  392. }
  393. PopupMenu popupMenu = tag.PopupMenu;
  394. BarButtonItem item = new BarButtonItem();
  395. item.ItemClick += (sender, e) =>
  396. {
  397. SaveFileDialog dialog = new SaveFileDialog();
  398. dialog.Filter = "csv|*.csv";
  399. if (dialog.ShowDialog() == DialogResult.OK)
  400. {
  401. var view = grid.MainView as GridView;
  402. view.ExportToCsv(dialog.FileName);
  403. }
  404. };
  405. item.ImageOptions.SvgImage = DxHelper.SvgHelper.CreateExportCsv();
  406. item.Caption = "导出(CSV)";
  407. tag.BarM.Items.Add(item);
  408. popupMenu.AddItem(item);
  409. popupMenu.Manager = tag.BarM;
  410. tag.PopupMenu = popupMenu;
  411. return grid;
  412. }
  413. public static GridControl UseExportXlsx(this GridControl grid)
  414. {
  415. GridTag tag = grid.Tag as GridTag;
  416. if (tag.BarM == null)
  417. {
  418. tag.BarM = new BarManager();
  419. tag.BarM.Form = grid;
  420. }
  421. if (tag.PopupMenu == null)
  422. {
  423. tag.PopupMenu = new PopupMenu();
  424. }
  425. PopupMenu popupMenu = tag.PopupMenu;
  426. BarButtonItem item = new BarButtonItem();
  427. item.ItemClick += (sender, e) =>
  428. {
  429. SaveFileDialog dialog = new SaveFileDialog();
  430. dialog.Filter = "Excel文件|*.xlsx";
  431. if (dialog.ShowDialog() == DialogResult.OK)
  432. {
  433. var view = grid.MainView as GridView;
  434. view.ExportToXlsx(dialog.FileName);
  435. }
  436. };
  437. item.ImageOptions.SvgImage = DxHelper.SvgHelper.CreateExportXlsx();
  438. item.Caption = "导出(Excel)";
  439. tag.BarM.Items.Add(item);
  440. popupMenu.AddItem(item);
  441. popupMenu.Manager = tag.BarM;
  442. tag.PopupMenu = popupMenu;
  443. return grid;
  444. }
  445. private static void View_KeyUp(object sender, KeyEventArgs e)
  446. {
  447. if (e.Control && e.Shift & e.KeyCode == Keys.C)
  448. {
  449. var view = sender as GridView;
  450. if (view.FocusedColumn == null) return;
  451. var val = view.GetFocusedRowCellDisplayText(view.FocusedColumn);
  452. if (string.IsNullOrWhiteSpace(val)) return;
  453. Clipboard.SetText(val);
  454. }
  455. }
  456. private static void View_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
  457. {
  458. if (e.Column.ColumnType == typeof(DateTime) || e.Column.ColumnType == typeof(DateTime?))
  459. {
  460. if (e.Value == null) return;
  461. if (e.Column.FieldName == "SigTime")
  462. e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm:ss.fff");
  463. else
  464. e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm:ss");
  465. }
  466. }
  467. public static GridControl ShowColumn(this GridControl grid, params string[] colField)
  468. {
  469. var view = grid.MainView as GridView;
  470. if (view.Columns.Count == 0) return grid;
  471. if (colField == null || colField.Length == 0) return grid;
  472. foreach (GridColumn item in view.Columns)
  473. {
  474. if (colField.Contains(item.FieldName))
  475. item.Visible = true;
  476. }
  477. return grid;
  478. }
  479. public static GridControl UseMultiSelect(this GridControl grid)
  480. {
  481. var view = grid.MainView as GridView;
  482. view.OptionsSelection.MultiSelect = true;
  483. view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect;
  484. return grid;
  485. }
  486. public static GridControl UseGroup(this GridControl grid)
  487. {
  488. var view = grid.MainView as GridView;
  489. view.OptionsView.GroupFooterShowMode = GroupFooterShowMode.Hidden;
  490. view.OptionsView.ShowGroupPanel = true;
  491. view.OptionsCustomization.AllowGroup = true;
  492. view.OptionsCustomization.AllowSort = true;
  493. return grid;
  494. }
  495. public static GridControl UseFooter(this GridControl grid, Action<object, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs> act)
  496. {
  497. var view = grid.MainView as GridView;
  498. view.OptionsView.ShowFooter = true;
  499. view.CustomDrawFooter += (s, e) => act(s, e);
  500. return grid;
  501. }
  502. public static GridControl UseEdit(this GridControl grid)
  503. {
  504. var view = grid.MainView as GridView;
  505. view.OptionsBehavior.Editable = true;
  506. view.OptionsSelection.EnableAppearanceFocusedCell = true;
  507. foreach (GridColumn item in view.Columns)
  508. {
  509. item.OptionsColumn.AllowEdit = false;
  510. }
  511. return grid;
  512. }
  513. public static GridControl UseRowNumber(this GridControl grid)
  514. {
  515. var view = grid.MainView as GridView;
  516. view.OptionsView.ShowIndicator = true;
  517. view.CustomDrawRowIndicator += (s, e) =>
  518. {
  519. if (!e.Info.IsRowIndicator) return;
  520. if (e.RowHandle < 0) return;
  521. e.Handled = true;
  522. string txt = (e.RowHandle + 1).ToString();
  523. var txtSize = e.Graphics.MeasureString(txt, e.Appearance.Font);
  524. if (view.IndicatorWidth < txtSize.Width + 20)
  525. {
  526. view.IndicatorWidth++;
  527. }
  528. var loc = new PointF(e.Bounds.X + e.Bounds.Width / 2f - txtSize.Width / 2f + 2,
  529. e.Bounds.Y + e.Bounds.Height / 2f - txtSize.Height / 2f);
  530. e.Cache.FillRectangle(new SolidBrush(e.Appearance.BackColor), e.Bounds);
  531. e.Cache.DrawString(txt, e.Appearance.Font, new SolidBrush(e.Appearance.ForeColor), loc);
  532. };
  533. view.RowCountChanged += (sender, e) =>
  534. {
  535. if (view.RowCount == 0)
  536. view.IndicatorWidth = -1;
  537. else
  538. view.IndicatorWidth = view.RowCount.ToString().Length * 6 + 20;
  539. };
  540. return grid;
  541. }
  542. public static GridControl UseNullValueText(this GridControl grid, string nullText = "--")
  543. {
  544. var view = grid.MainView as GridView;
  545. view.CustomColumnDisplayText += (sender, e) =>
  546. {
  547. if (e.Value == null) e.DisplayText = nullText;
  548. };
  549. return grid;
  550. }
  551. public static GridControl SetDisplayText(this GridControl grid, string columnFieldName, Func<object, string> action)
  552. {
  553. var view = grid.MainView as GridView;
  554. view.CustomColumnDisplayText += (sender, e) =>
  555. {
  556. if (e.Column.FieldName != columnFieldName) return;
  557. if (e.Value == null || action == null) return;
  558. e.DisplayText = action(e.Value);
  559. };
  560. return grid;
  561. }
  562. public static GridControl HideColumn(this GridControl grid, params string[] colField)
  563. {
  564. var view = grid.MainView as GridView;
  565. if (colField == null || colField.Length == 0) return grid;
  566. foreach (GridColumn item in view.Columns)
  567. {
  568. if (colField.Contains(item.FieldName))
  569. item.Visible = false;
  570. }
  571. return grid;
  572. }
  573. public static GridControl AddMenu(this GridControl grid, string menuText, SvgImage meunImage, Action onClick)
  574. {
  575. GridTag tag = grid.Tag as GridTag;
  576. if (tag.BarM == null)
  577. {
  578. tag.BarM = new BarManager();
  579. tag.BarM.Form = grid;
  580. }
  581. if (tag.PopupMenu == null)
  582. {
  583. tag.PopupMenu = new PopupMenu();
  584. }
  585. PopupMenu popupMenu = tag.PopupMenu;
  586. BarButtonItem item = new BarButtonItem();
  587. item.ItemClick += (sender, e) =>
  588. {
  589. item.Enabled = false;
  590. onClick?.Invoke();
  591. item.Enabled = true;
  592. };
  593. item.ImageOptions.SvgImage = meunImage;
  594. item.Caption = menuText;
  595. tag.BarM.Items.Add(item);
  596. popupMenu.AddItem(item);
  597. popupMenu.Manager = tag.BarM;
  598. tag.PopupMenu = popupMenu;
  599. return grid;
  600. }
  601. /// <summary>
  602. /// GridControl添加单行元素选择后的右键菜单
  603. /// </summary>
  604. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  605. /// <param name="grid">GridControl控件</param>
  606. /// <param name="menuText">菜单标题</param>
  607. /// <param name="meunImage">菜单图标</param>
  608. /// <param name="action">菜单要执行的事件函数,参数为选中的单行元素</param>
  609. /// <param name="showCondition">菜单显示的条件</param>
  610. /// <returns></returns>
  611. public static GridControl AddRowMenu<T>(this GridControl grid, string menuText, SvgImage meunImage,
  612. Action<T> action, Func<T, bool> showCondition = null)
  613. {
  614. GridTag tag = grid.Tag as GridTag;
  615. var view = grid.MainView as GridView;
  616. if (tag.BarM == null)
  617. {
  618. tag.BarM = new BarManager();
  619. tag.BarM.Form = grid;
  620. }
  621. if (tag.PopupMenu == null)
  622. {
  623. tag.PopupMenu = new PopupMenu();
  624. }
  625. var popupMenu = tag.PopupMenu;
  626. BarButtonItem item = new BarButtonItem();
  627. tag.RowButtonsItems.Add(item);
  628. Func<bool> showConditionAll = () =>
  629. {
  630. if (!view.GetSelectedRows().Any()) return false;
  631. if (showCondition == null)
  632. return true;
  633. else
  634. return showCondition((T)view.GetFocusedRow());
  635. };
  636. item.Tag = showConditionAll;
  637. var handle = new ItemClickEventHandler((sender, e) =>
  638. {
  639. if (action != null)
  640. {
  641. if (view.GetFocusedRow() == null) return;
  642. item.Enabled = false;
  643. action.Invoke((T)view.GetFocusedRow());
  644. item.Enabled = true;
  645. }
  646. });
  647. item.Events().AddHandler(menuText, handle);
  648. item.ItemClick += handle;
  649. item.ImageOptions.SvgImage = meunImage;
  650. item.Caption = menuText;
  651. tag.BarM.Items.Add(item);
  652. popupMenu.AddItem(item);
  653. popupMenu.Manager = tag.BarM;
  654. tag.PopupMenu = popupMenu;
  655. return grid;
  656. }
  657. /// <summary>
  658. /// GridControl添加单行元素选择后的右键菜单
  659. /// </summary>
  660. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  661. /// <param name="grid">GridControl控件</param>
  662. /// <param name="menuText">菜单标题</param>
  663. /// <param name="meunImage">菜单图标</param>
  664. /// <param name="action">菜单要执行的异步事件函数,参数为选中的单行元素</param>
  665. /// <param name="showCondition">菜单显示的条件</param>
  666. /// <returns></returns>
  667. public static GridControl AddRowMenuAsync<T>(this GridControl grid, string menuText, SvgImage meunImage,
  668. Func<T, Task> action, Func<T, bool> showCondition = null)
  669. {
  670. GridTag tag = grid.Tag as GridTag;
  671. var view = grid.MainView as GridView;
  672. if (tag.BarM == null)
  673. {
  674. tag.BarM = new BarManager();
  675. tag.BarM.Form = grid;
  676. }
  677. if (tag.PopupMenu == null)
  678. {
  679. tag.PopupMenu = new PopupMenu();
  680. }
  681. var popupMenu = tag.PopupMenu;
  682. BarButtonItem item = new BarButtonItem();
  683. tag.RowButtonsItems.Add(item);
  684. Func<bool> showConditionAll = () =>
  685. {
  686. if (!view.GetSelectedRows().Any()) return false;
  687. if (showCondition == null)
  688. return true;
  689. else
  690. return showCondition((T)view.GetFocusedRow());
  691. };
  692. item.Tag = showConditionAll;
  693. var handle = new ItemClickEventHandler(async (sender, e) =>
  694. {
  695. if (action != null)
  696. {
  697. if (view.GetFocusedRow() == null) return;
  698. item.Enabled = false;
  699. await action.Invoke((T)view.GetFocusedRow());
  700. item.Enabled = true;
  701. }
  702. });
  703. item.Events().AddHandler(menuText, handle);
  704. item.ItemClick += handle;
  705. item.ImageOptions.SvgImage = meunImage;
  706. item.Caption = menuText;
  707. tag.BarM.Items.Add(item);
  708. popupMenu.AddItem(item);
  709. popupMenu.Manager = tag.BarM;
  710. tag.PopupMenu = popupMenu;
  711. return grid;
  712. }
  713. /// <summary>
  714. /// GridControl添加多行选择元素的右键菜单(自动启用UseMultiSelect)
  715. /// </summary>
  716. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  717. /// <param name="grid">GridControl控件</param>
  718. /// <param name="menuText">菜单标题</param>
  719. /// <param name="meunImage">菜单图标</param>
  720. /// <param name="action">菜单要执行的事件,参数为选中的一行或多行元素</param>
  721. /// <returns></returns>
  722. public static GridControl AddMultRowMenu<T>(this GridControl grid, string menuText, SvgImage meunImage,
  723. Action<List<T>> action)
  724. {
  725. grid.UseMultiSelect();
  726. GridTag tag = grid.Tag as GridTag;
  727. var view = grid.MainView as GridView;
  728. if (tag.BarM == null)
  729. {
  730. tag.BarM = new BarManager();
  731. tag.BarM.Form = grid;
  732. }
  733. if (tag.PopupMenu == null)
  734. {
  735. tag.PopupMenu = new PopupMenu();
  736. }
  737. var popupMenu = tag.PopupMenu;
  738. BarButtonItem item = new BarButtonItem();
  739. var handle = new ItemClickEventHandler((sender, e) =>
  740. {
  741. if (action != null)
  742. {
  743. var rows = view.GetSelectedRows();
  744. List<T> list = new List<T>();
  745. foreach (var row in rows)
  746. {
  747. if (row < 0) continue;
  748. list.Add((T)view.GetRow(row));
  749. }
  750. if (list.Any())
  751. action.Invoke(list);
  752. }
  753. });
  754. item.Events().AddHandler(menuText, handle);
  755. item.ItemClick += handle;
  756. item.ImageOptions.SvgImage = meunImage;
  757. item.Caption = menuText;
  758. Func<bool> showCondition = () => view.GetSelectedRows().Any();
  759. item.Tag = showCondition;
  760. tag.BarM.Items.Add(item);
  761. popupMenu.AddItem(item);
  762. popupMenu.Manager = tag.BarM;
  763. tag.PopupMenu = popupMenu;
  764. return grid;
  765. }
  766. /// <summary>
  767. /// GridControl添加多行选择元素的右键菜单(自动启用UseMultiSelect)
  768. /// </summary>
  769. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  770. /// <param name="grid">GridControl控件</param>
  771. /// <param name="menuText">菜单标题</param>
  772. /// <param name="meunImage">菜单图标</param>
  773. /// <param name="action">菜单要执行的异步事件函数,参数为选中的一行或多行元素</param>
  774. /// <returns></returns>
  775. public static GridControl AddMultRowMenuAsync<T>(this GridControl grid, string menuText, SvgImage meunImage,
  776. Func<List<T>, Task> action)
  777. {
  778. grid.UseMultiSelect();
  779. GridTag tag = grid.Tag as GridTag;
  780. var view = grid.MainView as GridView;
  781. if (tag.BarM == null)
  782. {
  783. tag.BarM = new BarManager();
  784. tag.BarM.Form = grid;
  785. }
  786. if (tag.PopupMenu == null)
  787. {
  788. tag.PopupMenu = new PopupMenu();
  789. }
  790. var popupMenu = tag.PopupMenu;
  791. BarButtonItem item = new BarButtonItem();
  792. var handle = new ItemClickEventHandler(async (sender, e) =>
  793. {
  794. if (action != null)
  795. {
  796. var rows = view.GetSelectedRows();
  797. List<T> list = new List<T>();
  798. foreach (var row in rows)
  799. {
  800. if (row < 0) continue;
  801. list.Add((T)view.GetRow(row));
  802. }
  803. if (list.Any())
  804. await action.Invoke(list);
  805. }
  806. });
  807. item.Events().AddHandler(menuText, handle);
  808. item.ItemClick += handle;
  809. item.ImageOptions.SvgImage = meunImage;
  810. item.Caption = menuText;
  811. Func<bool> showCondition = () => view.GetSelectedRows().Any();
  812. item.Tag = showCondition;
  813. tag.BarM.Items.Add(item);
  814. popupMenu.AddItem(item);
  815. popupMenu.Manager = tag.BarM;
  816. tag.PopupMenu = popupMenu;
  817. return grid;
  818. }
  819. /// <summary>
  820. /// GridControl添加内容区的右键菜单
  821. /// </summary>
  822. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  823. /// <param name="grid">GridControl控件</param>
  824. /// <param name="menuText">菜单标题</param>
  825. /// <param name="meunImage">菜单图标</param>
  826. /// <param name="action">菜单要执行的事件,参数为绑定的数据源</param>
  827. /// <param name="showWithNoneDataRow">内容区没有元素时是否显示此菜单,默认显示</param>
  828. /// <returns></returns>
  829. public static GridControl AddContentMenu<T>(this GridControl grid, string menuText, SvgImage meunImage,
  830. Action<List<T>> action, bool showWithNoneDataRow = true)
  831. {
  832. GridTag tag = grid.Tag as GridTag;
  833. var view = grid.MainView as GridView;
  834. if (tag.BarM == null)
  835. {
  836. tag.BarM = new BarManager();
  837. tag.BarM.Form = grid;
  838. }
  839. if (tag.PopupMenu == null)
  840. {
  841. tag.PopupMenu = new PopupMenu();
  842. }
  843. var popupMenu = tag.PopupMenu;
  844. BarButtonItem item = new BarButtonItem();
  845. var handle = new ItemClickEventHandler((sender, e) =>
  846. {
  847. if (action != null)
  848. {
  849. var ds = grid.DataSource as List<T>;
  850. if (!showWithNoneDataRow && (ds == null || ds.Count == 0)) return;
  851. item.Enabled = false;
  852. action.Invoke(ds);
  853. item.Enabled = true;
  854. }
  855. });
  856. item.Events().AddHandler(menuText, handle);
  857. item.ItemClick += handle;
  858. item.ImageOptions.SvgImage = meunImage;
  859. item.Caption = menuText;
  860. tag.BarM.Items.Add(item);
  861. popupMenu.AddItem(item);
  862. popupMenu.Manager = tag.BarM;
  863. tag.PopupMenu = popupMenu;
  864. return grid;
  865. }
  866. /// <summary>
  867. /// GridControl添加内容区的右键菜单
  868. /// </summary>
  869. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  870. /// <param name="grid">GridControl控件</param>
  871. /// <param name="menuText">菜单标题</param>
  872. /// <param name="meunImage">菜单图标</param>
  873. /// <param name="action">菜单要执行的事件,参数为绑定的数据源</param>
  874. /// <param name="showWithNoneDataRow">内容区没有元素时是否显示此菜单,默认显示</param>
  875. /// <returns></returns>
  876. public static GridControl AddContentMenuAsync<T>(this GridControl grid, string menuText, SvgImage meunImage,
  877. Func<List<T>, Task> action, bool showWithNoneDataRow = true)
  878. {
  879. GridTag tag = grid.Tag as GridTag;
  880. var view = grid.MainView as GridView;
  881. if (tag.BarM == null)
  882. {
  883. tag.BarM = new BarManager();
  884. tag.BarM.Form = grid;
  885. }
  886. if (tag.PopupMenu == null)
  887. {
  888. tag.PopupMenu = new PopupMenu();
  889. }
  890. var popupMenu = tag.PopupMenu;
  891. BarButtonItem item = new BarButtonItem();
  892. var handle = new ItemClickEventHandler(async (sender, e) =>
  893. {
  894. if (action != null)
  895. {
  896. var ds = grid.DataSource as List<T>;
  897. if (!showWithNoneDataRow && (ds == null || ds.Count == 0)) return;
  898. item.Enabled = false;
  899. await action.Invoke(ds);
  900. item.Enabled = true;
  901. }
  902. });
  903. item.Events().AddHandler(menuText, handle);
  904. item.ItemClick += handle;
  905. item.ImageOptions.SvgImage = meunImage;
  906. item.Caption = menuText;
  907. tag.BarM.Items.Add(item);
  908. popupMenu.AddItem(item);
  909. popupMenu.Manager = tag.BarM;
  910. tag.PopupMenu = popupMenu;
  911. return grid;
  912. }
  913. private static void View_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
  914. {
  915. if (e.Menu != null)
  916. {
  917. foreach (DXMenuItem item in e.Menu.Items)
  918. {
  919. if (!item.Enabled)
  920. {
  921. item.Visible = false;
  922. continue;
  923. }
  924. }
  925. }
  926. //if (e.HitInfo.HitTest == DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitTest.EmptyRow)
  927. //{
  928. // return;
  929. //}
  930. var view = sender as GridView;
  931. var grid = view.GridControl;
  932. var p = grid.PointToScreen(e.Point);
  933. var tag = grid.Tag as GridTag;
  934. if (tag?.PopupMenu != null)
  935. {
  936. foreach (BarButtonItemLink item in tag?.PopupMenu?.ItemLinks)
  937. {
  938. var buttonItem = item.Item;
  939. if (buttonItem.Tag != null && buttonItem.Tag is Func<bool> showCondition)
  940. {
  941. if (showCondition())
  942. buttonItem.Visibility = BarItemVisibility.Always;
  943. else
  944. buttonItem.Visibility = BarItemVisibility.Never;
  945. }
  946. }
  947. tag?.PopupMenu?.ShowPopup(p);
  948. }
  949. }
  950. public static GridControl DrawGridColumnHeaderCheckBox(this GridControl grid)
  951. {
  952. //View的 Editable要为true
  953. var view = grid.MainView as GridView;
  954. view.OptionsBehavior.Editable = true;
  955. view.OptionsSelection.MultiSelect = true;
  956. view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect;
  957. foreach (GridColumn item in view.Columns)
  958. {
  959. item.OptionsColumn.AllowEdit = false;
  960. }
  961. return grid;
  962. }
  963. }