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.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 AddMenu(this GridControl grid, string menuText, SvgImage meunImage, Action onClick)
  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. item.Enabled = false;
  431. onClick?.Invoke();
  432. item.Enabled = true;
  433. };
  434. item.ImageOptions.SvgImage = meunImage;
  435. item.Caption = menuText;
  436. tag.BarM.Items.Add(item);
  437. popupMenu.AddItem(item);
  438. popupMenu.Manager = tag.BarM;
  439. tag.PopupMenu = popupMenu;
  440. return grid;
  441. }
  442. public static GridControl UseExportXlsx(this GridControl grid)
  443. {
  444. GridTag tag = grid.Tag as GridTag;
  445. if (tag.BarM == null)
  446. {
  447. tag.BarM = new BarManager();
  448. tag.BarM.Form = grid;
  449. }
  450. if (tag.PopupMenu == null)
  451. {
  452. tag.PopupMenu = new PopupMenu();
  453. }
  454. PopupMenu popupMenu = tag.PopupMenu;
  455. BarButtonItem item = new BarButtonItem();
  456. item.ItemClick += (sender, e) =>
  457. {
  458. SaveFileDialog dialog = new SaveFileDialog();
  459. dialog.Filter = "Excel文件|*.xlsx";
  460. if (dialog.ShowDialog() == DialogResult.OK)
  461. {
  462. var view = grid.MainView as GridView;
  463. view.ExportToXlsx(dialog.FileName);
  464. }
  465. };
  466. item.ImageOptions.SvgImage = DxHelper.SvgHelper.CreateExportXlsx();
  467. item.Caption = "导出(Excel)";
  468. tag.BarM.Items.Add(item);
  469. popupMenu.AddItem(item);
  470. popupMenu.Manager = tag.BarM;
  471. tag.PopupMenu = popupMenu;
  472. return grid;
  473. }
  474. private static void View_KeyUp(object sender, KeyEventArgs e)
  475. {
  476. if (e.Control && e.Shift & e.KeyCode == Keys.C)
  477. {
  478. var view = sender as GridView;
  479. if (view.FocusedColumn == null) return;
  480. var val = view.GetFocusedRowCellDisplayText(view.FocusedColumn);
  481. if (string.IsNullOrWhiteSpace(val)) return;
  482. Clipboard.SetText(val);
  483. }
  484. }
  485. private static void View_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
  486. {
  487. if (e.Column.ColumnType == typeof(DateTime) || e.Column.ColumnType == typeof(DateTime?))
  488. {
  489. if (e.Value == null) return;
  490. if (e.Column.FieldName == "SigTime")
  491. e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm:ss.fff");
  492. else
  493. e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm:ss");
  494. }
  495. }
  496. public static GridControl ShowColumn(this GridControl grid, params string[] colField)
  497. {
  498. var view = grid.MainView as GridView;
  499. if (view.Columns.Count == 0) return grid;
  500. if (colField == null || colField.Length == 0) return grid;
  501. foreach (GridColumn item in view.Columns)
  502. {
  503. if (colField.Contains(item.FieldName))
  504. item.Visible = true;
  505. }
  506. return grid;
  507. }
  508. public static GridControl UseMultiSelect(this GridControl grid)
  509. {
  510. var view = grid.MainView as GridView;
  511. view.OptionsSelection.MultiSelect = true;
  512. view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect;
  513. return grid;
  514. }
  515. public static GridControl UseGroup(this GridControl grid)
  516. {
  517. var view = grid.MainView as GridView;
  518. view.OptionsView.GroupFooterShowMode = GroupFooterShowMode.Hidden;
  519. view.OptionsView.ShowGroupPanel = true;
  520. view.OptionsCustomization.AllowGroup = true;
  521. view.OptionsCustomization.AllowSort = true;
  522. return grid;
  523. }
  524. public static GridControl UseFooter(this GridControl grid, Action<object, DevExpress.XtraGrid.Views.Base.RowObjectCustomDrawEventArgs> act)
  525. {
  526. var view = grid.MainView as GridView;
  527. view.OptionsView.ShowFooter = true;
  528. view.CustomDrawFooter += (s, e) => act(s, e);
  529. return grid;
  530. }
  531. public static GridControl UseEdit(this GridControl grid)
  532. {
  533. var view = grid.MainView as GridView;
  534. view.OptionsBehavior.Editable = true;
  535. view.OptionsSelection.EnableAppearanceFocusedCell = true;
  536. foreach (GridColumn item in view.Columns)
  537. {
  538. item.OptionsColumn.AllowEdit = false;
  539. }
  540. return grid;
  541. }
  542. public static GridControl UseRowNumber(this GridControl grid)
  543. {
  544. var view = grid.MainView as GridView;
  545. view.OptionsView.ShowIndicator = true;
  546. view.CustomDrawRowIndicator += (s, e) =>
  547. {
  548. if (!e.Info.IsRowIndicator) return;
  549. if (e.RowHandle < 0) return;
  550. e.Handled = true;
  551. string txt = (e.RowHandle + 1).ToString();
  552. var txtSize = e.Graphics.MeasureString(txt, e.Appearance.Font);
  553. if (view.IndicatorWidth < txtSize.Width + 20)
  554. {
  555. view.IndicatorWidth++;
  556. }
  557. var loc = new PointF(e.Bounds.X + e.Bounds.Width / 2f - txtSize.Width / 2f + 2,
  558. e.Bounds.Y + e.Bounds.Height / 2f - txtSize.Height / 2f);
  559. e.Cache.FillRectangle(new SolidBrush(e.Appearance.BackColor), e.Bounds);
  560. e.Cache.DrawString(txt, e.Appearance.Font, new SolidBrush(e.Appearance.ForeColor), loc);
  561. };
  562. view.RowCountChanged += (sender, e) =>
  563. {
  564. if (view.RowCount == 0)
  565. view.IndicatorWidth = -1;
  566. else
  567. view.IndicatorWidth = view.RowCount.ToString().Length * 6 + 20;
  568. };
  569. return grid;
  570. }
  571. public static GridControl UseNullValueText(this GridControl grid, string nullText = "--")
  572. {
  573. var view = grid.MainView as GridView;
  574. view.CustomColumnDisplayText += (sender, e) =>
  575. {
  576. if (e.Value == null) e.DisplayText = nullText;
  577. };
  578. return grid;
  579. }
  580. public static GridControl SetDisplayText(this GridControl grid, string columnFieldName, Func<object, string> action)
  581. {
  582. var view = grid.MainView as GridView;
  583. view.CustomColumnDisplayText += (sender, e) =>
  584. {
  585. if (e.Column.FieldName != columnFieldName) return;
  586. if (e.Value == null || action == null) return;
  587. e.DisplayText = action(e.Value);
  588. };
  589. return grid;
  590. }
  591. public static GridControl HideColumn(this GridControl grid, params string[] colField)
  592. {
  593. var view = grid.MainView as GridView;
  594. if (colField == null || colField.Length == 0) return grid;
  595. foreach (GridColumn item in view.Columns)
  596. {
  597. if (colField.Contains(item.FieldName))
  598. item.Visible = false;
  599. }
  600. return grid;
  601. }
  602. /// <summary>
  603. /// GridControl添加单行元素选择后的右键菜单
  604. /// </summary>
  605. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  606. /// <param name="grid">GridControl控件</param>
  607. /// <param name="menuText">菜单标题</param>
  608. /// <param name="meunImage">菜单图标</param>
  609. /// <param name="action">菜单要执行的事件函数,参数为选中的单行元素</param>
  610. /// <param name="showCondition">菜单显示的条件</param>
  611. /// <returns></returns>
  612. public static GridControl AddRowMenu<T>(this GridControl grid, string menuText, SvgImage meunImage,
  613. Action<T> action, Func<T, bool> showCondition = null)
  614. {
  615. GridTag tag = grid.Tag as GridTag;
  616. var view = grid.MainView as GridView;
  617. if (tag.BarM == null)
  618. {
  619. tag.BarM = new BarManager();
  620. tag.BarM.Form = grid;
  621. }
  622. if (tag.PopupMenu == null)
  623. {
  624. tag.PopupMenu = new PopupMenu();
  625. }
  626. var popupMenu = tag.PopupMenu;
  627. BarButtonItem item = new BarButtonItem();
  628. tag.RowButtonsItems.Add(item);
  629. Func<bool> showConditionAll = () =>
  630. {
  631. if (!view.GetSelectedRows().Any()) return false;
  632. if (showCondition == null)
  633. return true;
  634. else
  635. return showCondition((T)view.GetFocusedRow());
  636. };
  637. item.Tag = showConditionAll;
  638. var handle = new ItemClickEventHandler((sender, e) =>
  639. {
  640. if (action != null)
  641. {
  642. if (view.GetFocusedRow() == null) return;
  643. item.Enabled = false;
  644. action.Invoke((T)view.GetFocusedRow());
  645. item.Enabled = true;
  646. }
  647. });
  648. item.Events().AddHandler(menuText, handle);
  649. item.ItemClick += handle;
  650. item.ImageOptions.SvgImage = meunImage;
  651. item.Caption = menuText;
  652. tag.BarM.Items.Add(item);
  653. popupMenu.AddItem(item);
  654. popupMenu.Manager = tag.BarM;
  655. tag.PopupMenu = popupMenu;
  656. return grid;
  657. }
  658. /// <summary>
  659. /// GridControl添加单行元素选择后的右键菜单
  660. /// </summary>
  661. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  662. /// <param name="grid">GridControl控件</param>
  663. /// <param name="menuText">菜单标题</param>
  664. /// <param name="meunImage">菜单图标</param>
  665. /// <param name="action">菜单要执行的异步事件函数,参数为选中的单行元素</param>
  666. /// <param name="showCondition">菜单显示的条件</param>
  667. /// <returns></returns>
  668. public static GridControl AddRowMenuAsync<T>(this GridControl grid, string menuText, SvgImage meunImage,
  669. Func<T, Task> action, Func<T, bool> showCondition = null)
  670. {
  671. GridTag tag = grid.Tag as GridTag;
  672. var view = grid.MainView as GridView;
  673. if (tag.BarM == null)
  674. {
  675. tag.BarM = new BarManager();
  676. tag.BarM.Form = grid;
  677. }
  678. if (tag.PopupMenu == null)
  679. {
  680. tag.PopupMenu = new PopupMenu();
  681. }
  682. var popupMenu = tag.PopupMenu;
  683. BarButtonItem item = new BarButtonItem();
  684. tag.RowButtonsItems.Add(item);
  685. Func<bool> showConditionAll = () =>
  686. {
  687. if (!view.GetSelectedRows().Any()) return false;
  688. if (showCondition == null)
  689. return true;
  690. else
  691. return showCondition((T)view.GetFocusedRow());
  692. };
  693. item.Tag = showConditionAll;
  694. var handle = new ItemClickEventHandler(async (sender, e) =>
  695. {
  696. if (action != null)
  697. {
  698. if (view.GetFocusedRow() == null) return;
  699. item.Enabled = false;
  700. await action.Invoke((T)view.GetFocusedRow());
  701. item.Enabled = true;
  702. }
  703. });
  704. item.Events().AddHandler(menuText, handle);
  705. item.ItemClick += handle;
  706. item.ImageOptions.SvgImage = meunImage;
  707. item.Caption = menuText;
  708. tag.BarM.Items.Add(item);
  709. popupMenu.AddItem(item);
  710. popupMenu.Manager = tag.BarM;
  711. tag.PopupMenu = popupMenu;
  712. return grid;
  713. }
  714. /// <summary>
  715. /// GridControl添加多行选择元素的右键菜单(自动启用UseMultiSelect)
  716. /// </summary>
  717. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  718. /// <param name="grid">GridControl控件</param>
  719. /// <param name="menuText">菜单标题</param>
  720. /// <param name="meunImage">菜单图标</param>
  721. /// <param name="action">菜单要执行的事件,参数为选中的一行或多行元素</param>
  722. /// <returns></returns>
  723. public static GridControl AddMultRowMenu<T>(this GridControl grid, string menuText, SvgImage meunImage,
  724. Action<List<T>> action)
  725. {
  726. grid.UseMultiSelect();
  727. GridTag tag = grid.Tag as GridTag;
  728. var view = grid.MainView as GridView;
  729. if (tag.BarM == null)
  730. {
  731. tag.BarM = new BarManager();
  732. tag.BarM.Form = grid;
  733. }
  734. if (tag.PopupMenu == null)
  735. {
  736. tag.PopupMenu = new PopupMenu();
  737. }
  738. var popupMenu = tag.PopupMenu;
  739. BarButtonItem item = new BarButtonItem();
  740. var handle = new ItemClickEventHandler((sender, e) =>
  741. {
  742. if (action != null)
  743. {
  744. var rows = view.GetSelectedRows();
  745. List<T> list = new List<T>();
  746. foreach (var row in rows)
  747. {
  748. if (row < 0) continue;
  749. list.Add((T)view.GetRow(row));
  750. }
  751. if (list.Any())
  752. action.Invoke(list);
  753. }
  754. });
  755. item.Events().AddHandler(menuText, handle);
  756. item.ItemClick += handle;
  757. item.ImageOptions.SvgImage = meunImage;
  758. item.Caption = menuText;
  759. Func<bool> showCondition = () => view.GetSelectedRows().Any();
  760. item.Tag = showCondition;
  761. tag.BarM.Items.Add(item);
  762. popupMenu.AddItem(item);
  763. popupMenu.Manager = tag.BarM;
  764. tag.PopupMenu = popupMenu;
  765. return grid;
  766. }
  767. /// <summary>
  768. /// GridControl添加多行选择元素的右键菜单(自动启用UseMultiSelect)
  769. /// </summary>
  770. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  771. /// <param name="grid">GridControl控件</param>
  772. /// <param name="menuText">菜单标题</param>
  773. /// <param name="meunImage">菜单图标</param>
  774. /// <param name="action">菜单要执行的异步事件函数,参数为选中的一行或多行元素</param>
  775. /// <returns></returns>
  776. public static GridControl AddMultRowMenuAsync<T>(this GridControl grid, string menuText, SvgImage meunImage,
  777. Func<List<T>, Task> action)
  778. {
  779. grid.UseMultiSelect();
  780. GridTag tag = grid.Tag as GridTag;
  781. var view = grid.MainView as GridView;
  782. if (tag.BarM == null)
  783. {
  784. tag.BarM = new BarManager();
  785. tag.BarM.Form = grid;
  786. }
  787. if (tag.PopupMenu == null)
  788. {
  789. tag.PopupMenu = new PopupMenu();
  790. }
  791. var popupMenu = tag.PopupMenu;
  792. BarButtonItem item = new BarButtonItem();
  793. var handle = new ItemClickEventHandler(async (sender, e) =>
  794. {
  795. if (action != null)
  796. {
  797. var rows = view.GetSelectedRows();
  798. List<T> list = new List<T>();
  799. foreach (var row in rows)
  800. {
  801. if (row < 0) continue;
  802. list.Add((T)view.GetRow(row));
  803. }
  804. if (list.Any())
  805. await action.Invoke(list);
  806. }
  807. });
  808. item.Events().AddHandler(menuText, handle);
  809. item.ItemClick += handle;
  810. item.ImageOptions.SvgImage = meunImage;
  811. item.Caption = menuText;
  812. Func<bool> showCondition = () => view.GetSelectedRows().Any();
  813. item.Tag = showCondition;
  814. tag.BarM.Items.Add(item);
  815. popupMenu.AddItem(item);
  816. popupMenu.Manager = tag.BarM;
  817. tag.PopupMenu = popupMenu;
  818. return grid;
  819. }
  820. /// <summary>
  821. /// GridControl添加内容区的右键菜单
  822. /// </summary>
  823. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  824. /// <param name="grid">GridControl控件</param>
  825. /// <param name="menuText">菜单标题</param>
  826. /// <param name="meunImage">菜单图标</param>
  827. /// <param name="action">菜单要执行的事件,参数为绑定的数据源</param>
  828. /// <param name="showWithNoneDataRow">内容区没有元素时是否显示此菜单,默认显示</param>
  829. /// <returns></returns>
  830. public static GridControl AddContentMenu<T>(this GridControl grid, string menuText, SvgImage meunImage,
  831. Action<List<T>> action, bool showWithNoneDataRow = true)
  832. {
  833. GridTag tag = grid.Tag as GridTag;
  834. var view = grid.MainView as GridView;
  835. if (tag.BarM == null)
  836. {
  837. tag.BarM = new BarManager();
  838. tag.BarM.Form = grid;
  839. }
  840. if (tag.PopupMenu == null)
  841. {
  842. tag.PopupMenu = new PopupMenu();
  843. }
  844. var popupMenu = tag.PopupMenu;
  845. BarButtonItem item = new BarButtonItem();
  846. var handle = new ItemClickEventHandler((sender, e) =>
  847. {
  848. if (action != null)
  849. {
  850. var ds = grid.DataSource as List<T>;
  851. if (!showWithNoneDataRow && (ds == null || ds.Count == 0)) return;
  852. item.Enabled = false;
  853. action.Invoke(ds);
  854. item.Enabled = true;
  855. }
  856. });
  857. item.Events().AddHandler(menuText, handle);
  858. item.ItemClick += handle;
  859. item.ImageOptions.SvgImage = meunImage;
  860. item.Caption = menuText;
  861. tag.BarM.Items.Add(item);
  862. popupMenu.AddItem(item);
  863. popupMenu.Manager = tag.BarM;
  864. tag.PopupMenu = popupMenu;
  865. return grid;
  866. }
  867. /// <summary>
  868. /// GridControl添加内容区的右键菜单
  869. /// </summary>
  870. /// <typeparam name="T">GridControl绑定数据源的泛型类型</typeparam>
  871. /// <param name="grid">GridControl控件</param>
  872. /// <param name="menuText">菜单标题</param>
  873. /// <param name="meunImage">菜单图标</param>
  874. /// <param name="action">菜单要执行的事件,参数为绑定的数据源</param>
  875. /// <param name="showWithNoneDataRow">内容区没有元素时是否显示此菜单,默认显示</param>
  876. /// <returns></returns>
  877. public static GridControl AddContentMenuAsync<T>(this GridControl grid, string menuText, SvgImage meunImage,
  878. Func<List<T>, Task> action, bool showWithNoneDataRow = true)
  879. {
  880. GridTag tag = grid.Tag as GridTag;
  881. var view = grid.MainView as GridView;
  882. if (tag.BarM == null)
  883. {
  884. tag.BarM = new BarManager();
  885. tag.BarM.Form = grid;
  886. }
  887. if (tag.PopupMenu == null)
  888. {
  889. tag.PopupMenu = new PopupMenu();
  890. }
  891. var popupMenu = tag.PopupMenu;
  892. BarButtonItem item = new BarButtonItem();
  893. var handle = new ItemClickEventHandler(async (sender, e) =>
  894. {
  895. if (action != null)
  896. {
  897. var ds = grid.DataSource as List<T>;
  898. if (!showWithNoneDataRow && (ds == null || ds.Count == 0)) return;
  899. item.Enabled = false;
  900. await action.Invoke(ds);
  901. item.Enabled = true;
  902. }
  903. });
  904. item.Events().AddHandler(menuText, handle);
  905. item.ItemClick += handle;
  906. item.ImageOptions.SvgImage = meunImage;
  907. item.Caption = menuText;
  908. tag.BarM.Items.Add(item);
  909. popupMenu.AddItem(item);
  910. popupMenu.Manager = tag.BarM;
  911. tag.PopupMenu = popupMenu;
  912. return grid;
  913. }
  914. private static void View_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
  915. {
  916. if (e.Menu != null)
  917. {
  918. foreach (DXMenuItem item in e.Menu.Items)
  919. {
  920. if (!item.Enabled)
  921. {
  922. item.Visible = false;
  923. continue;
  924. }
  925. }
  926. }
  927. //if (e.HitInfo.HitTest == DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitTest.EmptyRow)
  928. //{
  929. // return;
  930. //}
  931. var view = sender as GridView;
  932. var grid = view.GridControl;
  933. var p = grid.PointToScreen(e.Point);
  934. var tag = grid.Tag as GridTag;
  935. if (tag?.PopupMenu != null)
  936. {
  937. foreach (BarButtonItemLink item in tag?.PopupMenu?.ItemLinks)
  938. {
  939. var buttonItem = item.Item;
  940. if (buttonItem.Tag != null && buttonItem.Tag is Func<bool> showCondition)
  941. {
  942. if (showCondition())
  943. buttonItem.Visibility = BarItemVisibility.Always;
  944. else
  945. buttonItem.Visibility = BarItemVisibility.Never;
  946. }
  947. }
  948. tag?.PopupMenu?.ShowPopup(p);
  949. }
  950. }
  951. public static GridControl DrawGridColumnHeaderCheckBox(this GridControl grid)
  952. {
  953. //View的 Editable要为true
  954. var view = grid.MainView as GridView;
  955. view.OptionsBehavior.Editable = true;
  956. view.OptionsSelection.MultiSelect = true;
  957. view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect;
  958. foreach (GridColumn item in view.Columns)
  959. {
  960. item.OptionsColumn.AllowEdit = false;
  961. }
  962. return grid;
  963. }
  964. }