自定义GridControl编辑器

本文版权归博主 惊梦无痕 所有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作。原文地址

鉴于网上的针对GridControl的一些代码比较凌乱,且功能分散,故将整理过的代码分享出来。
本代码用的DevExpress版本号:17.2.6.0,旧的版本可能有些地方会有些微的变化。
目前该自定义编辑器中集成了一些比较实用的功能,希望对使用或正在学习DevExpress的同学有所帮助。
等下次有时间再把其他的一些自定义通用控件也发出来。

 

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Windows.Forms;
  7 using Comteck.Winforms.Controls.Components;
  8 using Comteck.Winforms.Utils;
  9 using DevExpress.Data.Filtering;
 10 using DevExpress.Utils;
 11 using DevExpress.Utils.Serializing;
 12 using DevExpress.XtraEditors;
 13 using DevExpress.XtraGrid;
 14 using DevExpress.XtraGrid.Columns;
 15 using DevExpress.XtraGrid.Registrator;
 16 using DevExpress.XtraGrid.Views.Base;
 17 using DevExpress.XtraGrid.Views.Base.Handler;
 18 using DevExpress.XtraGrid.Views.Base.ViewInfo;
 19 using DevExpress.XtraGrid.Views.Grid;
 20 using DevExpress.XtraGrid.Views.Grid.Drawing;
 21 using DevExpress.XtraGrid.Views.Grid.ViewInfo;
 22 
 23 namespace Comteck.Winforms.Controls {
 24   #region MyGridControl
 25 
 26   /// <summary>
 27   /// A grid view is represented by several classes. 
 28   ///   Please make sure that you inherit the appropriate class to implement a specific functionality:
 29   /// GridView - a central grid view class, which manages columns, view infos, a painter, mouse and keyboard handlers.
 30   /// GridHandler - processes the mouse and keyboard.
 31   /// GridViewInfo - calculates view information for drawing a grid view on screen.
 32   /// GridViewPrintInfo - calculates the information necessary to print a grid view.
 33   /// 
 34   /// Assume, you have created a GridView descendant and want to use your class with the GridControl at design time. 
 35   ///   You should do the following to register it:
 36   /// 1. Create a Registrator class (please see GridInfoRegistrator in ViewRegistrator.cs). 
 37   ///   Please note: you will need to be careful when overriding the ViewName property, 
 38   ///     because it is used to identify the view within the GridControl's descendant. 
 39   ///   Please make certain that you are using the same view name both in the registrator's ViewName property 
 40   ///     and within the GridControl's CreateDefaultView overridden method.
 41   /// 2. Inherit the GridControl class and override the RegisterAvailableViewsCore 
 42   ///   method (it was the RegisterAvailableViews method in XtraGrid 2).
 43   /// 3. If you want the GridControl to create an instance of your GridView by default,
 44   /// you should override the GridControl.CreateDefaultView method.
 45   /// 
 46   /// 创建自定义的MyGridControl
 47   /// <para>https://www.devexpress.com/Support/Center/Search/List/1?searchString=treelist</para>
 48   /// <para>http://www.dxper.net/thread-555-1-1.html</para>
 49   /// </summary>
 50   [ToolboxItem(true)]
 51   public class MyGridControl : GridControl {
 52     /// <summary>
 53     /// Create a new MyGridControl object
 54     /// </summary>
 55     public MyGridControl()
 56         : base() {
 57       // 使用内置的分页
 58       this.CustomInit();
 59     }
 60 
 61     /// <summary>
 62     /// 创建初始化的GridView视图(请参照第3点)
 63     /// </summary>
 64     /// <returns></returns>
 65     protected override BaseView CreateDefaultView() {
 66       return base.CreateView("MyGridView");
 67     }
 68 
 69     /// <summary>
 70     /// 向容器中注册所有的控件
 71     /// </summary>
 72     /// <param name="collection"></param>
 73     protected override void RegisterAvailableViewsCore(InfoCollection collection) {
 74       base.RegisterAvailableViewsCore(collection);
 75       collection.Add(new MyGridViewInfoRegistrator());
 76       collection.Add(new MyBandedGridInfoRegistrator());
 77     }
 78 
 79     /// <summary>
 80     /// 初始化内置的分页,如果要使用增、删、改功能,则把下面的代码注释即可
 81     /// </summary>
 82     private void InitNagigator() {
 83       this.EmbeddedNavigator.TextStringFormat = "记录 {0} / {1}";
 84       this.EmbeddedNavigator.Buttons.Append.Visible = false;
 85       this.EmbeddedNavigator.Buttons.Remove.Visible = false;
 86       this.EmbeddedNavigator.Buttons.Edit.Visible = false;
 87       this.EmbeddedNavigator.Buttons.EndEdit.Visible = false;
 88       this.EmbeddedNavigator.Buttons.CancelEdit.Visible = false;
 89     }
 90 
 91     private void CustomInit() {
 92       this.InitNagigator();
 93     }
 94   }
 95 
 96   #endregion
 97 
 98   #region 创建自定义的GridView
 99 
100   /// <summary>
101   /// 创建自定义的GridView
102   /// </summary>
103   public class MyGridView : GridView {
104     /// <summary>
105     /// DevExpress选择列的默认fieldname
106     /// </summary>
107     public const string DEVEXPRESS_SELECTION_NAME = "DX$CheckboxSelectorColumn";
108     /// <summary>
109     /// 当光标在末行最后一个指定字段时继续回车的跳转方式
110     /// </summary>
111     public enum EnumForwardType {
112       [Description("跳转到首行首列")]
113       Circle = 0,
114       [Description("停止跳转,直接返回")]
115       Stop = 1,
116       [Description("新增一行,光标定位到新行指定列")]
117       NewRow = 2,
118     }
119 
120     /// <summary>
121     /// Default View Name
122     /// </summary>
123     protected override string ViewName => "MyGridView";
124 
125     public delegate void AddNewLineDelegate();
126     /// <summary>
127     /// 新增行自定义事件
128     /// </summary>
129     public AddNewLineDelegate AddNewLineEventHandler;
130 
131     #region 自定义属性
132 
133     //
134     // 摘要:                                                        
135     //     当 GridView 没有数据时是否显示提示,提示的值由 EmptyForegroundText 属性设置
136     [DefaultValue(false),]
137     [DXCategory("自定义属性")]
138     [Description("当 GridView 没有数据时是否显示提示,提示的值由 EmptyForegroundText 属性设置")]
139     [XtraSerializableProperty]
140     public virtual bool EnableShowEmptyForeground { get; set; }
141     //
142     // 摘要:
143     //     当 GridView 没有数据时的默认提示. 
144     [DefaultValue(typeof(string), "")]
145     [DXCategory("自定义属性")]
146     [Description("当 GridView 没有数据时显示的值,默认显示\"没有查询到你所想要的数据!\"")]
147     [XtraSerializableProperty]
148     public virtual string EmptyForegroundText { get; set; }
149     //
150     // 摘要:
151     //     GridView 回车时按指定字段跳转到相应的单元格.   
152     //     调用方法如:new List<string>() { "SKUCODE", "PRICE", "DESCRIPTION" };   
153     [DefaultValue(typeof(List<string>), "")]
154     [DXCategory("自定义属性")]
155     [Description("指定可以跳转的列(FieldName),回车时按值先后顺序跳转")]
156     [XtraSerializableProperty]
157     [TypeConverter(typeof(CollectionConverter))]
158     [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
159     [Browsable(false)]
160     public virtual List<string> ForwardColumnList { get; set; }
161     //
162     // 摘要:
163     //     当光标在末行最后一个指定字段时继续回车的跳转方式.  
164     [DefaultValue(typeof(EnumForwardType), "Circle")]
165     [DXCategory("自定义属性")]
166     [Description("当光标在末行最后一个指定字段时继续回车的跳转方式")]
167     [XtraSerializableProperty]
168     public virtual EnumForwardType ForwardType { get; set; } = EnumForwardType.Circle;
169     //
170     // 摘要:
171     //     当末行最后一列回车新增行时,指定光标在新行定位的列(FieldName).
172     [DefaultValue(typeof(string), "")]
173     [DXCategory("自定义属性")]
174     [Description("当末行最后一列回车新增行时,指定光标在新行定位的列(FieldName),默认为新增行首个可编辑列")]
175     [XtraSerializableProperty]
176     public virtual string LocatedColumn { get; set; }
177 
178     #endregion
179 
180     #region 构造函数
181 
182     /// <summary>
183     /// 默认构造
184     /// </summary>
185     public MyGridView() {
186       this.OptionsFilter.ColumnFilterPopupMode = DevExpress.XtraGrid.Columns.ColumnFilterPopupMode.Classic;
187     }
188 
189     /// <summary>
190     /// 含参构造
191     /// </summary>
192     /// <param name="grid"></param>
193     public MyGridView(GridControl ownerGrid)
194         : base(ownerGrid) {
195       this.OptionsFilter.ColumnFilterPopupMode = DevExpress.XtraGrid.Columns.ColumnFilterPopupMode.Classic;
196     }
197 
198     #endregion
199 
200     #region 自定义方法
201 
202     /// <summary>
203     /// 初始化,设置默认值
204     /// </summary>
205     public void Initialize() {
206       // 设置为多选
207       this.OptionsSelection.MultiSelect = true;
208       // 自带勾选列的宽度
209       this.OptionsSelection.CheckBoxSelectorColumnWidth = 35;
210       // 选中序号列是否勾选
211       this.OptionsSelection.UseIndicatorForSelection = false;
212       // 隐藏提示
213       this.OptionsView.ShowGroupPanel = false;
214       // 是否自适应列宽度
215       this.OptionsView.ColumnAutoWidth = false;
216       // 是否启用偶数行外观                                               
217       this.OptionsView.EnableAppearanceEvenRow = true;
218       // 是否启用奇数行外观
219       this.OptionsView.EnableAppearanceOddRow = true;
220       // 是否显示过滤面板
221       this.OptionsView.ShowFilterPanelMode = ShowFilterPanelMode.Never;
222       // 是否显示子报表
223       this.OptionsDetail.EnableMasterViewMode = false;
224       // 筛选模式
225       this.OptionsFilter.ColumnFilterPopupMode = DevExpress.XtraGrid.Columns.ColumnFilterPopupMode.Classic;
226       // 编辑模式
227       this.OptionsBehavior.EditorShowMode = EditorShowMode.MouseUp;
228       // 打印效果
229       this.OptionsPrint.AutoWidth = false;
230       // 字段标题居中
231       this.Appearance.HeaderPanel.TextOptions.HAlignment = HorzAlignment.Center;
232       // 选中行颜色
233       this.SetAppearanceColor();
234       // 是否回车后光标移到下一个单元格
235       this.OptionsNavigation.EnterMoveNextColumn = true;
236       // 是否允许移动列
237       this.OptionsCustomization.AllowColumnMoving = false;
238       // 默认选中第一行                              
239       this.FocusedRowHandle = 0;
240       // 设置行号宽度
241       this.IndicatorWidth = 28;
242     }
243 
244     /// <summary>
245     /// 设置单元格是否可编辑
246     /// </summary>
247     /// <param name="editableColumnsList">当GridView可编辑时,指定可以编辑的列(FieldName).</param>
248     public void SetEditableColumns(List<string> editableColumnsList) {
249       if (this.OptionsBehavior.Editable && editableColumnsList != null && editableColumnsList.Count > 0) {
250         foreach (GridColumn col in this.Columns) {
251           if (editableColumnsList.Exists(x => x == col.FieldName)) {
252             // 设置标题字体色
253             col.AppearanceHeader.ForeColor = Color.Blue;
254             col.OptionsColumn.AllowEdit = true;
255           } else {
256             // 设置标题字体色
257             col.AppearanceHeader.ForeColor = Color.Black;
258             col.OptionsColumn.AllowEdit = false;
259           }
260         }
261       }
262     }
263 
264     /// <summary>
265     /// 判断是否为表格最后一列可编辑列
266     /// </summary>
267     /// <param name="view"></param>
268     /// <param name="focusedColumn"></param>
269     /// <returns></returns>
270     private bool IsLastEditableColumn(GridColumn focusedColumn) {
271       var index = this.VisibleColumns.IndexOf(focusedColumn);
272 
273       for (int i = this.VisibleColumns.Count - 1; i >= 0; i--) {
274         GridColumn column = this.VisibleColumns[i];
275         // 忽略不可编辑Column 
276         if (!column.OptionsColumn.AllowEdit) continue;
277         // 当前列如果是最后一列可编辑列,则返回True,否则返回False
278         return index == i;
279       }
280       // 如果都不可编辑,则返回False
281       return false;
282     }
283 
284     /// <summary>
285     /// 添加新行
286     /// </summary>
287     private void AddNewLine() {
288       var list = this.GridControl.DataSource;
289       // 获取当前实例的 Type
290       var t = this.DataSource.GetType();
291       // 动态创建实例
292       var obj = Activator.CreateInstance(t.GetGenericArguments()[0]);
293       // 调用公用方法 Add
294       var method = t.GetMethod("Add");
295       // 将构建好的实例添加到数据源中
296       method.Invoke(list, new object[] { obj });
297       // 刷新数据源
298       this.RefreshData();
299     }
300 
301     /// <summary>  
302     /// 获取GridView过滤或排序后的数据集  
303     /// </summary>  
304     /// <typeparam name="T">泛型对象</typeparam>  
305     /// <returns></returns>  
306     public IEnumerable<T> GetFilteredDataSource<T>() where T : class {
307       var list = new List<T>();
308       for (int i = 0; i < this.RowCount; i++) {
309         if (this.IsGroupRow(i)) continue;
310 
311         var entity = this.GetRow(i) as T;
312         if (entity == null) continue;
313 
314         list.Add(entity);
315       }
316       return list;
317     }
318 
319     /// <summary>
320     /// 获取GridView的选中行数据集(数据源是 DataTable)
321     /// </summary>
322     /// <returns></returns>
323     public DataTable GetSelectedDataRows() {
324       var dt = (this.DataSource as DataView).Table.Clone();
325       var rowIds = this.GetSelectedRows();
326 
327       foreach (var id in rowIds) {
328         var row = (this.GetRow(id) as DataRowView).Row;
329         if (row == null) continue;
330 
331         dt.Rows.Add(row.ItemArray);
332       }
333       return dt;
334     }
335 
336     #endregion
337 
338     /// <summary>
339     /// 在初始化后注册一些事件
340     /// </summary>
341     public override void EndInit() {
342       base.EndInit();
343 
344       // 针对MyGridLookUpEdit的情况
345       if (string.IsNullOrWhiteSpace(this.GridControl?.Name)) return;
346 
347       // 设置行号
348       this.CustomDrawRowIndicator += new RowIndicatorCustomDrawEventHandler(MyGridView_CustomDrawRowIndicator);
349       // 设置行号宽度
350       this.RowCountChanged += new EventHandler(MyGridView_RowCountChanged);
351       // 在查询得到0条记录时显示自定义的字符提示/显示
352       this.CustomDrawEmptyForeground += new CustomDrawEventHandler(MyGridView_CustomDrawEmptyForeground);
353       // 回车跳转单元格(配合 ForwardColumnList 使用)
354       this.KeyDown += new KeyEventHandler(MyGridView_KeyDown);
355     }
356 
357     /// <summary>
358     /// 设置自动行号
359     /// </summary>
360     /// <param name="sender"></param>
361     /// <param name="e"></param>
362     private void MyGridView_CustomDrawRowIndicator(object sender, RowIndicatorCustomDrawEventArgs e) {
363       if (e.Info.IsRowIndicator && e.RowHandle >= 0) {
364         e.Info.DisplayText = (e.RowHandle + 1).ToString();
365       }
366     }
367 
368     /// <summary>
369     /// 行号宽度随行数的变化而变化
370     /// </summary>
371     /// <param name="sender"></param>
372     /// <param name="e"></param>
373     private void MyGridView_RowCountChanged(object sender, EventArgs e) {
374       // 根据总行数设置行号宽度
375       this.IndicatorWidth = 28 + (this.RowCount.ToString().Length - 1) * 10;
376     }
377 
378     /// <summary>
379     /// 在查询得到0条记录时显示自定义的字符提示/显示
380     /// </summary>
381     /// <param name="sender"></param>
382     /// <param name="e"></param>
383     private void MyGridView_CustomDrawEmptyForeground(object sender, CustomDrawEventArgs e) {
384       if (!this.EnableShowEmptyForeground) return;
385 
386       string showText = string.IsNullOrWhiteSpace(this.EmptyForegroundText) ? "没有查询到你所想要的数据!" : this.EmptyForegroundText;
387 
388       //方法一(此方法为GridView设置了数据源绑定时,可用)
389       try {
390         var bindingSource = this.DataSource as BindingSource;
391         if (bindingSource.Count == 0) {
392           var str = showText;
393           var f = new Font("宋体", 10, FontStyle.Bold);
394           var r = new Rectangle(e.Bounds.Top + 5, e.Bounds.Left + 5, e.Bounds.Right - 5, e.Bounds.Height - 5);
395           e.Graphics.DrawString(str, f, Brushes.Black, r);
396         }
397       } catch {
398         //方法二(此方法为GridView没有设置数据源绑定时使用,一般使用此种方法)  
399         if (this.RowCount == 0) {
400           var str = showText;
401           var f = new Font("宋体", 10, FontStyle.Bold);
402           var r = new Rectangle(e.Bounds.Left + 5, e.Bounds.Top + 5, e.Bounds.Width - 5, e.Bounds.Height - 5);
403           e.Graphics.DrawString(str, f, Brushes.Black, r);
404         }
405       }
406     }
407 
408     #region 单元格回车事件
409 
410     /// <summary>
411     /// 默认情况下,回车或Tab按可编辑列跳转
412     /// </summary>
413     /// <param name="sender"></param>
414     /// <param name="e"></param>
415     private void OnDefaultKeyDown(object sender, KeyEventArgs e) {
416       if (!((e.KeyCode == Keys.Enter && this.OptionsNavigation.EnterMoveNextColumn) || e.KeyCode == Keys.Tab)) return;
417 
418       GridColumn column = null;
419       var index = this.VisibleColumns.IndexOf(this.FocusedColumn);
420 
421       // 光标是否在最后一列可编辑列
422       if (IsLastEditableColumn(this.FocusedColumn)) {
423         #region 判断是否到达末行
424 
425         if (this.FocusedRowHandle >= this.RowCount - 1) {
426           // 此处可选择跳转到首行或者直接返回或者新增行
427           switch (this.ForwardType) {
428             case EnumForwardType.Circle:  // 首行首列
429               this.MoveFirst();
430               for (int i = 0; i < this.VisibleColumns.Count; i++) {
431                 column = this.VisibleColumns[i];
432                 // 忽略不可编辑Column 
433                 if (!column.OptionsColumn.AllowEdit) continue;
434                 // 当前列可编辑,则光标定位到该列
435                 this.FocusedColumn = column;
436                 return;
437               }
438               break;
439             case EnumForwardType.Stop:    // 停止跳转,直接返回
440               e.Handled = true;
441               break;
442             case EnumForwardType.NewRow:  // 新增行,并跳转到新行首列
443               if (this.AddNewLineEventHandler == null)
444                 AddNewLine();
445               else
446                 AddNewLineEventHandler();
447 
448               this.MoveNext();
449               // 没有指定定位字段
450               if (string.IsNullOrWhiteSpace(this.LocatedColumn)) {
451                 for (int i = 0; i < this.VisibleColumns.Count; i++) {
452                   column = this.VisibleColumns[i];
453                   // 忽略不可编辑Column 
454                   if (!column.OptionsColumn.AllowEdit) continue;
455                   // 当前列可编辑,则光标定位到该列
456                   this.FocusedColumn = column;
457                   return;
458                 }
459               } else {
460                 this.FocusedColumn = this.Columns[this.LocatedColumn];
461               }
462               break;
463           }
464           return;
465         }
466 
467         #endregion
468 
469         this.MoveNext();
470         for (int i = 0; i < this.VisibleColumns.Count; i++) {
471           column = this.VisibleColumns[i];
472           // 忽略不可编辑Column 
473           if (!column.OptionsColumn.AllowEdit) continue;
474           // 如果是系统自带的编辑列,则直接跳过
475           if (column.FieldName == DEVEXPRESS_SELECTION_NAME) continue;
476 
477           // 当前列可编辑,则光标定位到该列
478           this.FocusedColumn = column;
479           return;
480         }
481       } else {
482         // 从当前定位列跳转到下一可编辑列
483         for (int i = index + 1; i < this.VisibleColumns.Count; i++) {
484           column = this.VisibleColumns[i];
485           // 忽略不可编辑Column 
486           if (!column.OptionsColumn.AllowEdit) continue;
487           // 如果是系统自带的编辑列,则直接跳过
488           if (column.FieldName == DEVEXPRESS_SELECTION_NAME) continue;
489 
490           // 当前列可编辑,则光标定位到该列
491           this.FocusedColumn = column;
492           return;
493         }
494 
495         // 如果光标在不可编辑列
496         for (int i = 0; i <= index; i++) {
497           column = this.VisibleColumns[i];
498           // 忽略不可编辑Column 
499           if (!column.OptionsColumn.AllowEdit) continue;
500           // 如果是系统自带的编辑列,则直接跳过
501           if (column.FieldName == DEVEXPRESS_SELECTION_NAME) continue; 
502           
503           // 当前列可编辑,则光标定位到该列
504           this.FocusedColumn = column;
505           return;
506         }
507       }
508     }
509 
510     /// <summary>
511     /// 自定义跳转,按指定列字段跳转
512     /// </summary>
513     /// <param name="sender"></param>
514     /// <param name="e"></param>
515     private void OnCustomerKeyDown(object sender, KeyEventArgs e) {
516       if (!((e.KeyCode == Keys.Enter && this.OptionsNavigation.EnterMoveNextColumn) || e.KeyCode == Keys.Tab)) return;
517 
518       var fieldName = this.FocusedColumn.FieldName;
519 
520       if (this.ForwardColumnList.Contains(fieldName)) {
521         var index = this.ForwardColumnList.IndexOf(fieldName);
522 
523         // 光标不在当前行指定列集合的最后一列
524         if (index != this.ForwardColumnList.Count - 1) {
525           this.FocusedColumn = this.Columns[this.ForwardColumnList[index + 1]];
526         } else  // 光标定位当前行指定列集合的最后一列
527           {
528           #region 判断是否到达末行
529 
530           if (this.FocusedRowHandle >= this.RowCount - 1) {
531             // 此处可选择跳转到首行或者直接返回或者新增行
532             switch (this.ForwardType) {
533               case EnumForwardType.Circle:  // 首行首列
534                 this.MoveFirst();
535                 this.FocusedColumn = this.Columns[this.ForwardColumnList[0]];
536                 break;
537               case EnumForwardType.Stop:    // 停止跳转,直接返回
538                 e.Handled = true;
539                 break;
540               case EnumForwardType.NewRow:  // 新增行,并跳转到新行首列
541                 if (this.AddNewLineEventHandler == null)
542                   AddNewLine();
543                 else
544                   AddNewLineEventHandler();
545 
546                 fieldName = string.IsNullOrWhiteSpace(this.LocatedColumn) ? this.ForwardColumnList[0] : this.LocatedColumn;
547 
548                 this.MoveNext();
549                 this.FocusedColumn = this.Columns[fieldName];
550                 break;
551             }
552             return;
553           }
554 
555           #endregion
556 
557           this.MoveNext();
558           this.FocusedColumn = this.Columns[this.ForwardColumnList[0]];
559         }
560       } else {
561         this.FocusedColumn = this.Columns[this.ForwardColumnList[0]];
562       }
563     }
564 
565     /// <summary>
566     /// 回车跳转单元格 
567     /// </summary>
568     /// <param name="sender"></param>
569     /// <param name="e"></param>
570     private void MyGridView_KeyDown(object sender, KeyEventArgs e) {
571       if (!((e.KeyCode == Keys.Enter && this.OptionsNavigation.EnterMoveNextColumn) || e.KeyCode == Keys.Tab)) return;
572 
573       if (this.ValidateEditor() == false) {
574         return;
575       }
576 
577       // 未设置,则按默认规则跳转
578       if (this.ForwardColumnList == null || this.ForwardColumnList.Count == 0) {
579         OnDefaultKeyDown(sender, e);
580       } else {
581         OnCustomerKeyDown(sender, e);
582       }
583     }
584 
585     #endregion
586 
587     #region GridLookUpEdit 模糊匹配
588 
589     /// <summary>
590     /// SetGridControlAccessMethod,主要是了MyGridLookUpEdit用
591     /// </summary>
592     /// <param name="newControl"></param>
593     protected internal virtual void SetGridControlAccessMethod(GridControl newControl) {
594       SetGridControl(newControl);
595     }
596 
597     /// <summary>
598     /// GridLookUpEdit的模糊匹配
599     /// </summary>
600     /// <param name="text"></param>
601     /// <param name="displayMember"></param>
602     /// <returns></returns>
603     protected override string OnCreateLookupDisplayFilter(string text, string displayMember) {
604       var subStringOperators = new List<CriteriaOperator>();
605       foreach (var sString in text.Split(' ')) {
606         var columnsOperators = new List<CriteriaOperator>();
607 
608         foreach (GridColumn col in this.Columns) {
609           columnsOperators.Add(new FunctionOperator(FunctionOperatorType.Contains, new OperandProperty(col.FieldName), sString));
610         }
611 
612         subStringOperators.Add(new GroupOperator(GroupOperatorType.Or, columnsOperators));
613       }
614 
615       return new GroupOperator(GroupOperatorType.And, subStringOperators).ToString();
616     }
617 
618     /// <summary>
619     /// 模糊匹配的字符串
620     /// </summary>
621     protected virtual internal string GetExtraFilterText => base.ExtraFilterText;
622     
623     #endregion
624 
625     #region 重写属性
626 
627     /// <summary>
628     /// 
629     /// </summary>
630     /// <returns></returns>
631     protected override ColumnViewOptionsView CreateOptionsView() {
632       return new CustomGridOptionsView();
633     }
634 
635     #endregion
636   }
637 
638   #endregion
639 
640   #region MyGridHandler processes the mouse and keyboard.
641 
642   /// <summary>
643   /// processes the mouse and keyboard.
644   /// </summary>
645   public class MyGridHandler : DevExpress.XtraGrid.Views.Grid.Handler.GridHandler {
646     /// <summary>
647     /// Constructor
648     /// </summary>
649     /// <param name="gridView"></param>
650     public MyGridHandler(GridView gridView)
651         : base(gridView) {
652     }
653 
654     /// <summary>
655     /// 重写事件 OnKeyDown
656     /// </summary>
657     /// <param name="e"></param>
658     protected override void OnKeyDown(KeyEventArgs e) {
659       try {
660         base.OnKeyDown(e);
661       } catch { }
662 
663       // Ctrl + C 复制单元格
664       if (e.Control & e.KeyCode == Keys.C) {
665         try {
666           Clipboard.SetDataObject(this.View.GetFocusedRowCellDisplayText(this.View.FocusedColumn));
667           e.Handled = true;
668         } catch { }
669       }
670     }
671   }
672 
673   #endregion
674 
675   #region MyGridViewInfoRegistrator
676 
677   /// <summary>
678   /// GridInfoRegistrator,注册MyGridView
679   /// </summary>
680   public class MyGridViewInfoRegistrator : GridInfoRegistrator {
681     protected const string MyGridViewName = "MyGridView";
682 
683     /// <summary>
684     /// Default View Name
685     /// </summary>
686     public override string ViewName => MyGridViewName;
687 
688     /// <summary>
689     /// 创建GridView
690     /// </summary>
691     /// <param name="grid"></param>
692     /// <returns></returns>
693     public override BaseView CreateView(GridControl grid) {
694       // 主要为了GridLookUpEdit用
695       var view = new MyGridView();
696       view.SetGridControlAccessMethod(grid);
697       view.Initialize();
698       return view;
699     }
700 
701     /// <summary>
702     /// CreateViewInfo
703     /// </summary>
704     /// <param name="view"></param>
705     /// <returns></returns>
706     public override BaseViewInfo CreateViewInfo(BaseView view) {
707       return new MyGridViewInfo(view as MyGridView);
708     }
709 
710     /// <summary>
711     /// 创建自定义的事件
712     /// </summary>
713     /// <param name="view"></param>
714     /// <returns></returns>
715     public override BaseViewHandler CreateHandler(BaseView view) {
716       return new MyGridHandler(view as MyGridView);
717     }
718 
719     /// <summary>
720     /// 创建自定义的绘画
721     /// </summary>
722     /// <param name="view"></param>
723     /// <returns></returns>
724     public override BaseViewPainter CreatePainter(BaseView view) {
725       return new MyGridPainter(view as GridView);
726     }
727   }
728 
729   #endregion
730 
731   #region MyGridViewInfo calculates view information for drawing a grid view on screen.
732 
733   /// <summary>
734   /// calculates view information for drawing a grid view on screen.
735   /// </summary>
736   public class MyGridViewInfo : GridViewInfo {
737     /// <summary>
738     /// Constructor
739     /// </summary>
740     /// <param name="gridView"></param>
741     public MyGridViewInfo(GridView gridView)
742         : base(gridView) { }
743   }
744 
745   #endregion
746 
747   #region GridPainter
748 
749   /// <summary>
750   /// 自定义画笔
751   /// </summary>
752   public class MyGridPainter : GridPainter {
753     /// <summary>
754     /// Constructor
755     /// </summary>
756     /// <param name="view"></param>
757     public MyGridPainter(GridView view) : base(view) { }
758 
759     /// <summary>
760     /// 创建视图
761     /// </summary>
762     public virtual new MyGridView View => (MyGridView)base.View;
763 
764     /// <summary>
765     /// 绘制行信息,主要为了MyGridLookUpEdit
766     /// </summary>
767     /// <param name="e"></param>
768     /// <param name="cell"></param>
769     protected override void DrawRowCell(GridViewDrawArgs e, GridCellInfo cell) {
770       cell.ViewInfo.MatchedStringUseContains = true;
771       // 匹配表达式
772       cell.ViewInfo.MatchedString = this.View.GetExtraFilterText;
773       // 单元格状态
774       cell.State = GridRowCellState.Dirty;
775       // 更新行
776       e.ViewInfo.UpdateCellAppearance(cell);
777       // Draw
778       base.DrawRowCell(e, cell);
779     }
780   }
781 
782   #endregion
783 }

 

posted @ 2019-02-18 15:37  惊梦无痕  阅读(1487)  评论(0编辑  收藏  举报