using DevExpress.Utils; using DevExpress.Utils.Helpers; using DevExpress.Utils.Menu; using DevExpress.Utils.Svg; using DevExpress.XtraBars; using DevExpress.XtraEditors; using DevExpress.XtraEditors.Controls; using DevExpress.XtraEditors.Repository; using DevExpress.XtraGrid; using DevExpress.XtraGrid.Columns; using DevExpress.XtraGrid.Views.Grid; using DevExpress.XtraRichEdit.Model; using DxHelper; using ExtensionsDev; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; public static class GridControlEx { internal class GridTag { public GridTag() { } public PopupMenu PopupMenu { get; set; } public BarManager BarM { get; set; } public List RowButtonsItems { get; set; } = new List(); public List MultRowButtonsItems { get; set; } = new List(); } /// /// 初始化表格(默认禁用分组) /// /// /// 绑定的数据源 /// 行高(默认24px) /// 是否显示水平滚动条(默认不显示) /// 绑定的数据源模型类型 /// public static GridControl UseDefault(this GridControl grid, List dataSource, int rowHeight = 24, bool showScrollH = false, bool formatNullValue = true) { grid.DataSource = dataSource; grid.Load += (sender, e) => { grid.HideColumn("UpdateTime"); grid.HideColumn(p => p.FieldName.ToUpper().EndsWith("ID")); grid.HideColumn(p => p.ColumnType == typeof(List<>)); grid.HideColumn(p => p.ColumnType == typeof(ICollection<>)); grid.HideColumn(p => p.ColumnType.BaseType != null && p.ColumnType.BaseType.Name.Contains("BaseEntity")); }; grid.MainView.BorderStyle = BorderStyles.Flat; var view = grid.MainView as GridView; SetViewDefaultProps(grid, view, rowHeight, showScrollH); var childView = grid.GetChildView(); if (childView != null) { view.OptionsView.ShowDetailButtons = true; SetViewDefaultProps(grid, childView, rowHeight, showScrollH); childView.OptionsMenu.EnableColumnMenu = false; childView.OptionsCustomization.AllowSort = false; childView.OptionsCustomization.AllowFilter = false; childView.OptionsCustomization.AllowGroup = false; } grid.Tag = new GridTag(); if (formatNullValue) grid.UseNullValueText(); return grid; } /// /// 初始化表格(默认禁用分组) /// /// /// 绑定的数据源 /// 行高(默认24px) /// 是否显示水平滚动条(默认不显示) /// 绑定的数据源模型类型 /// public static GridControl UseDefaultEx(this GridControl grid, BindingList dataSource, int rowHeight = 24, bool showScrollH = false, bool formatNullValue = true) { grid.DataSource = dataSource; grid.Load += (sender, e) => { grid.HideColumn("UpdateTime"); grid.HideColumn(p => p.FieldName.ToUpper().EndsWith("ID")); grid.HideColumn(p => p.ColumnType == typeof(List<>)); grid.HideColumn(p => p.ColumnType == typeof(ICollection<>)); grid.HideColumn(p => p.ColumnType.BaseType != null && p.ColumnType.BaseType.Name.Contains("BaseEntity")); }; grid.MainView.BorderStyle = BorderStyles.Flat; var view = grid.MainView as GridView; SetViewDefaultProps(grid, view, rowHeight, showScrollH); var childView = grid.GetChildView(); if (childView != null) { view.OptionsView.ShowDetailButtons = true; SetViewDefaultProps(grid, childView, rowHeight, showScrollH); childView.OptionsMenu.EnableColumnMenu = false; childView.OptionsCustomization.AllowSort = false; childView.OptionsCustomization.AllowFilter = false; childView.OptionsCustomization.AllowGroup = false; } grid.Tag = new GridTag(); if (formatNullValue) grid.UseNullValueText(); return grid; } public static GridView GetChildView(this GridControl grid) { return grid.LevelTree?.Nodes?.FirstOrDefault()?.LevelTemplate as GridView; } public static GridControl UseEditForm(this GridControl grid, int columnCount, params string[] columns) { var view = grid.MainView as GridView; view.OptionsBehavior.Editable = true; view.OptionsBehavior.EditingMode = DevExpress.XtraGrid.Views.Grid.GridEditingMode.EditForm; //foreach (GridColumn item in view.Columns) //{ // if (item.VisibleIndex > 0) // item.OptionsEditForm.VisibleIndex = item.VisibleIndex; //} var maxIdx = view.Columns.Max(p => p.OptionsEditForm.VisibleIndex); for (int i = 0; i < columns.Length; i++) { view.Columns[columns[i]].OptionsEditForm.Visible = DefaultBoolean.True; view.Columns[columns[i]].OptionsEditForm.VisibleIndex = maxIdx + i + 1; } return grid; } private static void SetViewDefaultProps(GridControl grid, GridView view, int rowHeight, bool showScrollH) { view.CustomColumnDisplayText += View_CustomColumnDisplayText; view.OptionsView.ShowButtonMode = DevExpress.XtraGrid.Views.Base.ShowButtonModeEnum.ShowAlways; view.Appearance.HeaderPanel.TextOptions.HAlignment = HorzAlignment.Center; view.Appearance.Row.Options.UseTextOptions = true; view.Appearance.Row.TextOptions.HAlignment = HorzAlignment.Center; view.OptionsView.ColumnHeaderAutoHeight = DefaultBoolean.True; view.RowHeight = rowHeight; view.OptionsView.ShowGroupPanel = false; view.OptionsDetail.ShowDetailTabs = false; view.OptionsDetail.AllowZoomDetail = false; view.OptionsBehavior.Editable = false; view.OptionsView.ShowDetailButtons = false; view.OptionsView.ShowIndicator = false; view.OptionsMenu.EnableColumnMenu = true; view.OptionsCustomization.AllowFilter = true; view.OptionsCustomization.AllowGroup = false; view.OptionsCustomization.AllowSort = true; view.OptionsCustomization.AllowColumnMoving = true; view.OptionsCustomization.AllowMergedGrouping = DefaultBoolean.False; view.OptionsSelection.MultiSelect = false; view.OptionsCustomization.AllowRowSizing = false; view.OptionsCustomization.AllowQuickHideColumns = false; view.OptionsMenu.EnableGroupPanelMenu = false; view.OptionsMenu.EnableGroupRowMenu = false; view.OptionsMenu.EnableFooterMenu = false; view.OptionsLayout.StoreAllOptions = true; view.OptionsLayout.StoreAppearance = true; view.OptionsLayout.StoreDataSettings = true; view.OptionsLayout.StoreVisualOptions = true; view.OptionsLayout.StoreFormatRules = true; view.OptionsView.ColumnAutoWidth = !showScrollH; view.PopupMenuShowing += View_PopupMenuShowing; view.OptionsSelection.EnableAppearanceFocusedCell = false; string GetLayoutName() { Control ctrl = null; if (view.Tag is SearchLookUpEdit searchLookUpEdit) { ctrl = searchLookUpEdit; } else { ctrl = grid; } while (ctrl.Parent != null) { ctrl = ctrl.Parent; if (ctrl is UserControl) break; if (ctrl is Form) break; } if (ctrl is not UserControl && ctrl is not Form) return null; //var props = typeof(T).GetProperties(); //StringBuilder sb = new StringBuilder(); //foreach (var item in props) //{ // sb.Append(item.Name); //} //var md5 = MD5Helper.StrToMD5(sb.ToString()); if (view.Tag is SearchLookUpEdit searchLookUpEdit2) return $"{ctrl.Name}_{searchLookUpEdit2.Name}"; else return $"{ctrl.Name}_{grid.Name}_{view.Name}"; } string name = GetLayoutName(); if (!string.IsNullOrWhiteSpace(name)) { view.Layout += (sender, e) => { Directory.CreateDirectory("Layout"); if (name == null) return; (sender as GridView).SaveLayoutToXml($"Layout\\{name}.xml", OptionsLayoutBase.FullLayout); }; } if (!string.IsNullOrWhiteSpace(name) && File.Exists($"Layout\\{name}.xml")) { view.RestoreLayoutFromXml($"Layout\\{name}.xml", OptionsLayoutBase.FullLayout); view.ClearColumnsFilter(); view.ClearFindFilter(); view.ClearInHeaderSearchText(); view.ClearSorting(); view.ClearSelection(); } view.KeyUp += View_KeyUp; } /// /// 为GirdControl启用右键新增数据的功能 /// /// /// /// public static GridControl UseEmptyText(this GridControl grid, string emptyText = "暂无数据") { if (string.IsNullOrWhiteSpace(emptyText)) return grid; var view = grid.MainView as GridView; view.CustomDrawEmptyForeground += (sender, e) => { var s = e.Appearance.CalcTextSize(e.Cache, emptyText, e.Bounds.Width).ToSize(); var x = (e.Bounds.Width - s.Width) / 2; var y = (e.Bounds.Height - s.Height) / 2; e.Appearance.ForeColor = Color.Gray; e.Appearance.DrawString(e.Cache, emptyText, new Rectangle(x, y + 20, s.Width, s.Height)); }; return grid; } /// /// 为GirdControl启用右键新增数据的功能 /// /// /// /// /// 一个回调函数,返回新增的数据 /// public static GridControl UseAdd(this GridControl grid, Func callback, string menuCaption = "新增") { var view = grid.MainView as GridView; view.CustomDrawEmptyForeground += (sender, e) => { string emptyText = "右键添加"; var s = e.Appearance.CalcTextSize(e.Cache, emptyText, e.Bounds.Width).ToSize(); var x = (e.Bounds.Width - s.Width) / 2; var y = (e.Bounds.Height - s.Height) / 2; e.Appearance.ForeColor = Color.Gray; e.Appearance.DrawString(e.Cache, emptyText, new Rectangle(x, y, s.Width, s.Height)); }; grid.AddContentMenu(menuCaption, DxHelper.SvgHelper.CreateAdd(), data => { if (callback != null) { var addRow = callback(); if (addRow == null) return; if (grid.DataSource is List ds) { ds.Add(addRow); } else if (grid.DataSource is BindingList bl) { bl.Add(addRow); } view.RefreshData(); } }, true); return grid; } /// /// 为GirdControl启用右键新增数据的功能 /// /// /// /// /// 一个回调函数,返回新增的数据 /// public static GridControl UseAddAsync(this GridControl grid, Func> callback, string menuCaption = "新增") { grid.AddContentMenuAsync(menuCaption, DxHelper.SvgHelper.CreateAdd(), async data => { if (callback != null) { var addRow = await callback(); if (addRow == null) return; var view = grid.MainView as GridView; if (grid.DataSource is List ds) { ds.Add(addRow); } else if (grid.DataSource is BindingList bl) { bl.Add(addRow); } view.RefreshData(); } }, true); return grid; } /// /// 为GridControl启用右编辑选中的单行功能 /// /// /// /// /// /// public static GridControl UseEdit(this GridControl grid, Func callback, string menuCaption = "编辑") { grid.AddRowMenu(menuCaption, DxHelper.SvgHelper.CreateEdit(), data => { if (callback != null) { var newRow = callback(data); if (newRow == null) return; var view = grid.MainView as GridView; if (grid.DataSource is List ds) { var idx=ds.IndexOf(data); ds.Remove(data); ds.Insert(idx, newRow); } else if (grid.DataSource is BindingList bl) { var idx = bl.IndexOf(data); bl.Remove(data); bl.Insert(idx, newRow); } view.RefreshData(); } }, null); return grid; } /// /// 为GridControl启用右编辑选中的单行功能 /// /// /// /// /// /// public static GridControl UseEditAsync(this GridControl grid, Func> callback, string menuCaption = "编辑") { grid.AddRowMenu(menuCaption, DxHelper.SvgHelper.CreateEdit(), async data => { if (callback != null) { var newRow = await callback(data); if (newRow == null) return; var view = grid.MainView as GridView; if (grid.DataSource is List ds) { var idx = ds.IndexOf(data); ds.Remove(data); ds.Insert(idx, newRow); } else if (grid.DataSource is BindingList bl) { var idx = bl.IndexOf(data); bl.Remove(data); bl.Insert(idx, newRow); } view.RefreshData(); } }, null); return grid; } /// /// 为GridControl启用右删除选中的一行或多行功能(自动启用UseMultiSelect) /// /// /// /// /// /// public static GridControl UseDelete(this GridControl grid, Func, bool> action = null, string menuCaption = "删除") { grid.AddMultRowMenu(menuCaption, DxHelper.SvgHelper.CreateClose(), data => { if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认删除选中的记录?共[{data.Count}]条")) return; if (action != null) { bool succeed = action(data); if (!succeed) return; } var view = grid.MainView as GridView; view.DeleteSelectedRows(); view.RefreshData(); }); return grid; } /// /// 为GridControl启用右删除选中的一行或多行功能(自动启用UseMultiSelect) /// /// /// /// /// /// public static GridControl UseDeleteAsync(this GridControl grid, Func, Task> action = null, string menuCaption = "删除") { grid.AddMultRowMenu(menuCaption, DxHelper.SvgHelper.CreateClose(), async data => { if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认删除选中的记录?共[{data.Count()}]条")) return; if (action != null) { bool succeed = await action(data); if (!succeed) return; } var view = grid.MainView as GridView; view.DeleteSelectedRows(); view.RefreshData(); }); return grid; } /// /// 为GirdControl启用右键清除所有数据的功能 /// /// /// /// /// /// public static GridControl UseClear(this GridControl grid, Func, bool> action = null, string menuCaption = "清除") { grid.AddContentMenu(menuCaption, DxHelper.SvgHelper.CreateClear(), data => { if (data == null || data.Count == 0) return; if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认清空所有记录?共[{data.Count}]条")) return; if (action != null) { bool succeed = action(data); if (!succeed) return; } var view = grid.MainView as GridView; data.Clear(); view.RefreshData(); }, false); return grid; } public static GridControl SetLogImageColumn(this GridControl grid, string columnFieldName, Type enumType) { var view = grid.MainView as GridView; RepositoryItemImageComboBox edit = new RepositoryItemImageComboBox(); edit.AddEnum(enumType); SvgImageCollection svgImages = new SvgImageCollection(); svgImages.ImageSize = new System.Drawing.Size(20, 20); svgImages.Add(SvgHelper.CreateInfo()); svgImages.Add(SvgHelper.CreateWarning()); svgImages.Add(SvgHelper.CreateError()); edit.SmallImages = svgImages; edit.GlyphAlignment = DevExpress.Utils.HorzAlignment.Center; view.Columns[columnFieldName].ColumnEdit = edit; view.Columns[columnFieldName].VisibleIndex = 0; view.Columns[columnFieldName].MaxWidth = 64; view.Columns[columnFieldName].MinWidth = 64; return grid; } public static GridControl SetStateImageColumn(this GridControl grid, string columnFieldName, Type enumType) { var view = grid.MainView as GridView; RepositoryItemImageComboBox edit = new RepositoryItemImageComboBox(); edit.AddEnum(enumType); SvgImageCollection svgImages = new SvgImageCollection(); svgImages.ImageSize = new System.Drawing.Size(20, 20); svgImages.Add(SvgHelper.CreateTskStateStoped()); svgImages.Add(SvgHelper.CreateTskStateWaitToRun()); svgImages.Add(SvgHelper.CreateTskStateRunning()); svgImages.Add(SvgHelper.CreateTskStateStopping()); edit.SmallImages = svgImages; edit.GlyphAlignment = DevExpress.Utils.HorzAlignment.Center; view.Columns[columnFieldName].ColumnEdit = edit; view.Columns[columnFieldName].VisibleIndex = 0; view.Columns[columnFieldName].MaxWidth = 64; view.Columns[columnFieldName].MinWidth = 64; return grid; } public static GridControl UseRowFocusedStyle(this GridControl grid) { var view = grid.MainView as GridView; view.OptionsSelection.EnableAppearanceFocusedCell = false; view.FocusRectStyle = DrawFocusRectStyle.RowFocus; var childView = grid.GetChildView(); if (childView != null) { childView.OptionsSelection.EnableAppearanceFocusedCell = false; childView.FocusRectStyle = DrawFocusRectStyle.RowFocus; } return grid; } public static GridControl UseFileChooseColumn(this GridControl grid, string columnFieldName, bool columnCanInput = false) { var view = grid.MainView as GridView; var edit = new RepositoryItemButtonEdit() { AutoHeight = false }; edit.ReadOnly = !columnCanInput; view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; edit.ButtonClick += (sender, e) => { OpenFileDialog dlg = new OpenFileDialog(); dlg.Title = "文件选择"; dlg.Multiselect = false; if (dlg.ShowDialog() == DialogResult.OK) { view.SetFocusedRowCellValue(columnFieldName, dlg.FileName); } }; return grid; } public static GridControl UseHttpDownloadColumn(this GridControl grid, string columnFieldName) { grid.UseEdit(false); var view = grid.MainView as GridView; var edit = new RepositoryItemButtonEdit() { AutoHeight = false, ReadOnly = true }; edit.Buttons[0].Kind = ButtonPredefines.Glyph; edit.Buttons[0].ToolTip = "下载文件"; edit.TextEditStyle = TextEditStyles.DisableTextEditor; edit.Buttons[0].ImageOptions.SvgImage = SvgHelper.CreateDownload(width: 12, height: 12); view.Columns[columnFieldName].OptionsColumn.AllowEdit = true; view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; edit.ButtonClick += async (sender, e) => { var url = view.GetFocusedRowCellValue(columnFieldName)?.ToString(); if (string.IsNullOrWhiteSpace(url)) return; var localFile = Path.GetFileName(url); SaveFileDialog d = new SaveFileDialog(); d.FileName = localFile; if (d.ShowDialog() == DialogResult.OK) { try { if (await HttpHelper.DownloadAsync(url, d.FileName)) { var dir = Path.GetDirectoryName(d.FileName); System.Diagnostics.Process.Start("explorer.exe", dir); } else { throw new Exception($"文件下载失败,url={url}"); } } catch (Exception ex) { throw new Exception($"文件下载失败,url={url}",ex); } } }; return grid; } public static GridControl UseBoolColumn(this GridControl grid, string columnFieldName, string trueText = "是", string falseText = "否", GridView view = null) { if (view == null) view = grid.MainView as GridView; var edit = new RepositoryItemImageComboBox() { AutoHeight = false }; edit.Items.Add(new ImageComboBoxItem(trueText, true)); edit.Items.Add(new ImageComboBoxItem(falseText, false)); edit.ReadOnly = false; view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; if (columnFieldName == "Enable") view.Columns[columnFieldName].VisibleIndex = 99; return grid; } public static GridControl UseLookUpEditColumn(this GridControl grid, string columnFieldName, string displayField = "", GridView view = null) { if (view == null) view = grid.MainView as GridView; var edit = new RepositoryItemLookUpEdit(); edit.AutoHeight = false; edit.ValueMember = "Id"; edit.DisplayMember = displayField; edit.NullText = "未知"; view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; return grid; } public static GridControl UseButtonEditColumn(this GridControl grid, string columnFieldName, GridView view = null) { grid.UseEdit(false); if (view == null) view = grid.MainView as GridView; var edit = new RepositoryItemButtonEdit(); edit.Buttons.Clear(); edit.Buttons.Add(new EditorButton(ButtonPredefines.Glyph) { Caption="Click"}); edit.AutoHeight = false; edit.TextEditStyle = TextEditStyles.HideTextEditor; view.Columns[columnFieldName].OptionsColumn.AllowEdit = true; view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; return grid; } public static GridControl UseDateTimeEditColumn(this GridControl grid, string columnFieldName, GridView view = null) { if (view == null) view = grid.MainView as GridView; var edit = new RepositoryItemDateEdit(); edit.AllowNullInput = DevExpress.Utils.DefaultBoolean.False; edit.AutoHeight = false; edit.CalendarTimeEditing = DevExpress.Utils.DefaultBoolean.True; edit.CalendarTimeProperties.DisplayFormat.FormatString = "HH:mm:ss"; edit.CalendarTimeProperties.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; edit.CalendarTimeProperties.EditFormat.FormatString = "HH:mm:ss"; edit.CalendarTimeProperties.EditFormat.FormatType = DevExpress.Utils.FormatType.DateTime; edit.CalendarTimeProperties.MaskSettings.Set("mask", "HH:mm:ss"); edit.DisplayFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; edit.DisplayFormat.FormatType = DevExpress.Utils.FormatType.DateTime; edit.EditFormat.FormatString = "yyyy-MM-dd HH:mm:ss"; edit.EditFormat.FormatType = DevExpress.Utils.FormatType.DateTime; edit.MaskSettings.Set("mask", "yyyy-MM-dd HH:mm:ss"); view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; return grid; } public static void UpdateLookUpEditDataSource(this GridControl grid, string columnFieldName, List dataSource, GridView view = null) { if (view == null) view = grid.MainView as GridView; var edit = view.Columns[columnFieldName].ColumnEdit as RepositoryItemLookUpEdit; if (edit != null) edit.DataSource = dataSource; } public static GridControl UseSearchEditColumn(this GridControl grid, string columnFieldName, List editDataSource, string displayField = "This", GridView view = null) { if (view == null) view = grid.MainView as GridView; var edit = new RepositoryItemSearchLookUpEdit(); SearchLookUpEdit dd; Control ctrl = grid; while (ctrl.Parent != null) { ctrl = ctrl.Parent; if (ctrl is UserControl) break; } var searchEdit1View = new DevExpress.XtraGrid.Views.Grid.GridView(); searchEdit1View.FocusRectStyle = DevExpress.XtraGrid.Views.Grid.DrawFocusRectStyle.RowFocus; searchEdit1View.OptionsSelection.EnableAppearanceFocusedCell = false; searchEdit1View.OptionsView.ShowGroupPanel = false; edit.Name = $"{ctrl.Name}_{grid.Name}_{columnFieldName}_SearchEdit"; edit.AutoHeight = false; edit.PopupView = searchEdit1View; edit.ValueMember = "Id"; edit.KeyMember = "Id"; edit.DisplayMember = displayField; edit.UseDefault().SetData(editDataSource); view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; searchEdit1View.GridControl.UseDefault(null); return grid; } public static GridControl UseSearchEditColumn(this GridControl grid, string columnFieldName, Func>> onGetData, string displayField = "This", GridView view = null) { if (view == null) view = grid.MainView as GridView; var edit = new RepositoryItemSearchLookUpEdit(); edit.DataSource = onGetData().Result; Control ctrl = grid; while (ctrl.Parent != null) { ctrl = ctrl.Parent; if (ctrl is UserControl) break; } var searchEdit1View = new DevExpress.XtraGrid.Views.Grid.GridView(); searchEdit1View.FocusRectStyle = DevExpress.XtraGrid.Views.Grid.DrawFocusRectStyle.RowFocus; searchEdit1View.OptionsSelection.EnableAppearanceFocusedCell = false; searchEdit1View.OptionsView.ShowGroupPanel = false; edit.Name = $"{ctrl.Name}_{grid.Name}_{columnFieldName}_SearchEdit"; edit.AutoHeight = false; edit.PopupView = searchEdit1View; edit.ValueMember = "Id"; edit.KeyMember = "Id"; edit.DisplayMember = displayField; edit.UseDefault().SetData(onGetData); view.Columns[columnFieldName].Visible = true; view.Columns[columnFieldName].ColumnEdit = edit; searchEdit1View.GridControl.UseDefault(null); return grid; } /// /// 为GirdControl启用右键清除所有数据的功能 /// /// /// /// /// /// public static GridControl UseClearAsync(this GridControl grid, Func, Task> action = null, string menuCaption = "清除") { grid.AddContentMenu(menuCaption, DxHelper.SvgHelper.CreateClear(), async data => { if (data == null || data.Count == 0) return; if (!DxHelper.MsgBoxHelper.ShowConfirm($"确认清空所有记录?共[{data.Count}]条")) return; if (action != null) { bool succeed = await action(data); if (!succeed) return; } var view = grid.MainView as GridView; data.Clear(); view.RefreshData(); }, false); return grid; } public static GridControl UseExportCsv(this GridControl grid) { GridTag tag = grid.Tag as GridTag; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } PopupMenu popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); item.ItemClick += (sender, e) => { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "csv|*.csv"; if (dialog.ShowDialog() == DialogResult.OK) { var view = grid.MainView as GridView; view.ExportToCsv(dialog.FileName); } }; item.ImageOptions.SvgImage = DxHelper.SvgHelper.CreateExportCsv(); item.Caption = "导出(CSV)"; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } public static GridControl AddMenu(this GridControl grid, string menuText, SvgImage meunImage, Action onClick) { GridTag tag = grid.Tag as GridTag; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } PopupMenu popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); item.ItemClick += (sender, e) => { item.Enabled = false; onClick?.Invoke(); item.Enabled = true; }; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } public static GridControl UseExportXlsx(this GridControl grid) { GridTag tag = grid.Tag as GridTag; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } PopupMenu popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); item.ItemClick += (sender, e) => { SaveFileDialog dialog = new SaveFileDialog(); dialog.Filter = "Excel文件|*.xlsx"; if (dialog.ShowDialog() == DialogResult.OK) { var view = grid.MainView as GridView; view.ExportToXlsx(dialog.FileName); } }; item.ImageOptions.SvgImage = DxHelper.SvgHelper.CreateExportXlsx(); item.Caption = "导出(Excel)"; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } private static void View_KeyUp(object sender, KeyEventArgs e) { if (e.Control && e.Shift & e.KeyCode == Keys.C) { var view = sender as GridView; if (view.FocusedColumn == null) return; var val = view.GetFocusedRowCellDisplayText(view.FocusedColumn); if (string.IsNullOrWhiteSpace(val)) return; Clipboard.SetText(val); } } private static void View_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e) { if (e.Column.ColumnType == typeof(DateTime) || e.Column.ColumnType == typeof(DateTime?)) { if (e.Value == null) return; if (e.Column.ColumnType == typeof(DateTime)) e.DisplayText = Convert.ToDateTime(e.Value).ToString("yyyy-MM-dd HH:mm:ss"); } } public static GridControl ShowColumn(this GridControl grid, params string[] colField) { var view = grid.MainView as GridView; if (view.Columns.Count == 0) return grid; if (colField == null || colField.Length == 0) return grid; foreach (GridColumn item in view.Columns) { if (colField.Contains(item.FieldName)) item.Visible = true; } return grid; } public static GridControl UseMultiSelect(this GridControl grid, bool useCheckBoxSelect = false) { var view = grid.MainView as GridView; view.OptionsSelection.MultiSelect = true; if (useCheckBoxSelect) view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect; else view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.RowSelect; return grid; } public static GridControl UseGroup(this GridControl grid) { var view = grid.MainView as GridView; view.OptionsView.GroupFooterShowMode = GroupFooterShowMode.Hidden; view.OptionsView.ShowGroupPanel = true; view.OptionsCustomization.AllowGroup = true; view.OptionsCustomization.AllowSort = true; return grid; } public static GridControl UseFooter(this GridControl grid, Action act) { var view = grid.MainView as GridView; view.OptionsView.ShowFooter = true; view.CustomDrawFooter += (s, e) => act(s, e); return grid; } public static GridControl UseEdit(this GridControl grid, bool columnsEdit = false) { var view = grid.MainView as GridView; view.OptionsBehavior.Editable = true; view.OptionsSelection.EnableAppearanceFocusedCell = true; foreach (GridColumn item in view.Columns) { item.OptionsColumn.AllowEdit = columnsEdit; } return grid; } public static GridControl UseRowNumber(this GridControl grid) { var view = grid.MainView as GridView; view.OptionsView.ShowIndicator = true; view.CustomDrawRowIndicator += (s, e) => { if (!e.Info.IsRowIndicator) return; if (e.RowHandle < 0) return; e.Handled = true; string txt = (e.RowHandle + 1).ToString(); var txtSize = e.Graphics.MeasureString(txt, e.Appearance.Font); if (view.IndicatorWidth < txtSize.Width + 20) { view.IndicatorWidth++; } var loc = new PointF(e.Bounds.X + e.Bounds.Width / 2f - txtSize.Width / 2f + 2, e.Bounds.Y + e.Bounds.Height / 2f - txtSize.Height / 2f); e.Cache.FillRectangle(new SolidBrush(e.Appearance.BackColor), e.Bounds); e.Cache.DrawString(txt, e.Appearance.Font, new SolidBrush(e.Appearance.ForeColor), loc); }; view.RowCountChanged += (sender, e) => { if (view.RowCount == 0) view.IndicatorWidth = -1; else view.IndicatorWidth = view.RowCount.ToString().Length * 6 + 20; }; return grid; } private static GridControl UseNullValueText(this GridControl grid, string nullText = "--") { var view = grid.MainView as GridView; view.CustomColumnDisplayText += (sender, e) => { if (e.Value == null || e.Value.ToString().Trim() == "") e.DisplayText = nullText; }; return grid; } public static GridControl SetDisplayText(this GridControl grid, string columnFieldName, Func action) { var view = grid.MainView as GridView; view.CustomColumnDisplayText += (sender, e) => { if (e.Column.FieldName != columnFieldName) return; if (e.Value == null || action == null) return; e.DisplayText = action(e.Value); }; return grid; } /// /// 隐藏指定字段的列 /// /// /// /// public static GridControl HideColumn(this GridControl grid, params string[] colField) { colField = colField.Select(t => t.ToLower()).ToArray(); var view = grid.MainView as GridView; if (colField == null || colField.Length == 0) return grid; foreach (GridColumn item in view.Columns) { if (colField.Contains(item.FieldName.ToLower())) item.Visible = false; } return grid; } /// /// 根据条件隐藏列(只会处理ColumnEdit==null的列) /// /// /// /// public static GridControl HideColumn(this GridControl grid, Func condition) { var view = grid.MainView as GridView; foreach (GridColumn item in view.Columns) { if (item.ColumnEdit == null && condition(item)) item.Visible = false; } return grid; } /// /// GridControl添加单行元素选择后的右键菜单 /// /// GridControl绑定数据源的泛型类型 /// GridControl控件 /// 菜单标题 /// 菜单图标 /// 菜单要执行的事件函数,参数为选中的单行元素 /// 菜单显示的条件 /// public static GridControl AddRowMenu(this GridControl grid, string menuText, SvgImage meunImage, Action action, Func showCondition = null) { GridTag tag = grid.Tag as GridTag; var view = grid.MainView as GridView; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } var popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); tag.RowButtonsItems.Add(item); Func showConditionAll = () => { if (!view.GetSelectedRows().Any()) return false; if (showCondition == null) return true; else return showCondition((T)view.GetFocusedRow()); }; item.Tag = showConditionAll; var handle = new ItemClickEventHandler((sender, e) => { if (action != null) { if (view.GetFocusedRow() == null) return; item.Enabled = false; action.Invoke((T)view.GetFocusedRow()); item.Enabled = true; } }); item.Events().AddHandler(menuText, handle); item.ItemClick += handle; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } /// /// GridControl添加单行元素选择后的右键菜单 /// /// GridControl绑定数据源的泛型类型 /// GridControl控件 /// 菜单标题 /// 菜单图标 /// 菜单要执行的异步事件函数,参数为选中的单行元素 /// 菜单显示的条件 /// public static GridControl AddRowMenuAsync(this GridControl grid, string menuText, SvgImage meunImage, Func action, Func showCondition = null) { GridTag tag = grid.Tag as GridTag; var view = grid.MainView as GridView; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } var popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); tag.RowButtonsItems.Add(item); Func showConditionAll = () => { if (!view.GetSelectedRows().Any()) return false; if (showCondition == null) return true; else return showCondition((T)view.GetFocusedRow()); }; item.Tag = showConditionAll; var handle = new ItemClickEventHandler(async (sender, e) => { if (action != null) { if (view.GetFocusedRow() == null) return; item.Enabled = false; await action.Invoke((T)view.GetFocusedRow()); item.Enabled = true; } }); item.Events().AddHandler(menuText, handle); item.ItemClick += handle; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } /// /// GridControl添加多行选择元素的右键菜单(自动启用UseMultiSelect) /// /// GridControl绑定数据源的泛型类型 /// GridControl控件 /// 菜单标题 /// 菜单图标 /// 菜单要执行的事件,参数为选中的一行或多行元素 /// public static GridControl AddMultRowMenu(this GridControl grid, string menuText, SvgImage meunImage, Action> action) { grid.UseMultiSelect(); GridTag tag = grid.Tag as GridTag; var view = grid.MainView as GridView; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } var popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); var handle = new ItemClickEventHandler((sender, e) => { if (action != null) { var rows = view.GetSelectedRows(); List list = new List(); foreach (var row in rows) { if (row < 0) continue; list.Add((T)view.GetRow(row)); } if (list.Any()) action.Invoke(list); } }); item.Events().AddHandler(menuText, handle); item.ItemClick += handle; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; Func showCondition = () => view.GetSelectedRows().Any(); item.Tag = showCondition; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } /// /// GridControl添加多行选择元素的右键菜单(自动启用UseMultiSelect) /// /// GridControl绑定数据源的泛型类型 /// GridControl控件 /// 菜单标题 /// 菜单图标 /// 菜单要执行的异步事件函数,参数为选中的一行或多行元素 /// public static GridControl AddMultRowMenuAsync(this GridControl grid, string menuText, SvgImage meunImage, Func, Task> action) { grid.UseMultiSelect(); GridTag tag = grid.Tag as GridTag; var view = grid.MainView as GridView; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } var popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); var handle = new ItemClickEventHandler(async (sender, e) => { if (action != null) { var rows = view.GetSelectedRows(); List list = new List(); foreach (var row in rows) { if (row < 0) continue; list.Add((T)view.GetRow(row)); } if (list.Any()) await action.Invoke(list); } }); item.Events().AddHandler(menuText, handle); item.ItemClick += handle; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; Func showCondition = () => view.GetSelectedRows().Any(); item.Tag = showCondition; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } /// /// GridControl添加内容区的右键菜单 /// /// GridControl绑定数据源的泛型类型 /// GridControl控件 /// 菜单标题 /// 菜单图标 /// 菜单要执行的事件,参数为绑定的数据源 /// 内容区没有元素时是否显示此菜单,默认显示 /// public static GridControl AddContentMenu(this GridControl grid, string menuText, SvgImage meunImage, Action> action, bool showWithNoneDataRow = true) { GridTag tag = grid.Tag as GridTag; var view = grid.MainView as GridView; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } var popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); var handle = new ItemClickEventHandler((sender, e) => { if (action != null) { if (grid.DataSource is List ds) { if (!showWithNoneDataRow && (ds == null || ds.Count == 0)) return; item.Enabled = false; action.Invoke(ds); } else if (grid.DataSource is BindingList bl) { if (!showWithNoneDataRow && (bl == null || bl.Count == 0)) return; item.Enabled = false; action.Invoke(bl.ToList()); } item.Enabled = true; } }); item.Events().AddHandler(menuText, handle); item.ItemClick += handle; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } /// /// GridControl添加内容区的右键菜单 /// /// GridControl绑定数据源的泛型类型 /// GridControl控件 /// 菜单标题 /// 菜单图标 /// 菜单要执行的事件,参数为绑定的数据源 /// 内容区没有元素时是否显示此菜单,默认显示 /// public static GridControl AddContentMenuAsync(this GridControl grid, string menuText, SvgImage meunImage, Func, Task> action, bool showWithNoneDataRow = true) { GridTag tag = grid.Tag as GridTag; var view = grid.MainView as GridView; if (tag.BarM == null) { tag.BarM = new BarManager(); tag.BarM.Form = grid; } if (tag.PopupMenu == null) { tag.PopupMenu = new PopupMenu(); } var popupMenu = tag.PopupMenu; BarButtonItem item = new BarButtonItem(); var handle = new ItemClickEventHandler(async (sender, e) => { if (action != null) { if (grid.DataSource is List ds) { if (!showWithNoneDataRow && (ds == null || ds.Count == 0)) return; item.Enabled = false; await action.Invoke(ds); } else if (grid.DataSource is BindingList bl) { if (!showWithNoneDataRow && (bl == null || bl.Count == 0)) return; item.Enabled = false; await action.Invoke(bl.ToList()); } item.Enabled = true; } }); item.Events().AddHandler(menuText, handle); item.ItemClick += handle; item.ImageOptions.SvgImage = meunImage; item.Caption = menuText; tag.BarM.Items.Add(item); popupMenu.AddItem(item); popupMenu.Manager = tag.BarM; tag.PopupMenu = popupMenu; return grid; } private static void View_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e) { if (e.Menu != null) { foreach (DXMenuItem item in e.Menu.Items) { if (!item.Enabled) { item.Visible = false; continue; } } } //if (e.HitInfo.HitTest == DevExpress.XtraGrid.Views.Grid.ViewInfo.GridHitTest.EmptyRow) //{ // return; //} var view = sender as GridView; var grid = view.GridControl; var p = grid.PointToScreen(e.Point); var tag = grid.Tag as GridTag; if (tag?.PopupMenu != null) { foreach (BarButtonItemLink item in tag?.PopupMenu?.ItemLinks) { var buttonItem = item.Item; if (buttonItem.Tag != null && buttonItem.Tag is Func showCondition) { if (showCondition()) buttonItem.Visibility = BarItemVisibility.Always; else buttonItem.Visibility = BarItemVisibility.Never; } } tag?.PopupMenu?.ShowPopup(p); } } public static GridControl DrawGridColumnHeaderCheckBox(this GridControl grid) { //View的 Editable要为true var view = grid.MainView as GridView; view.OptionsBehavior.Editable = true; view.OptionsSelection.MultiSelect = true; view.OptionsSelection.MultiSelectMode = GridMultiSelectMode.CheckBoxRowSelect; foreach (GridColumn item in view.Columns) { item.OptionsColumn.AllowEdit = false; } return grid; } }