GridControlEx.cs 36 KB

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