- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
DevExpress的GridControl控件能够提供很多强大的操作,其视图GridView能够通过各种设置,呈现出多种复杂的界面效果,本篇随笔探讨一些常见的GridControl控件及其GridView的视图操作处理,以便在大家也需要的时候作为一个参考的代码。其中设计一些常见的操作,如合并单元格、汇总统计、复制粘贴行、导入数据处理、导出Excel、导出PDF等、打印GridView视图、内置插入及保存数据处理等等.
有时候,需要把多行紧挨着的单元格内容进行合并展示,这样有助于界面的美观及查看便利,如下界面所示.
或者这样的界面,都是类似的效果.
合并的处理比较简单,只需要设置允许合并,以及实现合并的处理事件代码即可。 。
// 允许合并 this .gridView1.OptionsView.AllowCellMerge = true ;
然后实现的事件代码如下所示.
private List< string > mergeFields = new List< string > { " 订单号 " , " 客户订单号 " , " 客户编码 " , " 客户名称 ", "组合编码", "组合名称" }; private void GridView1_CellMerge( object sender, CellMergeEventArgs e) { var fieldName = e.Column.FieldName; if (mergeFields.Contains(fieldName)) { var view = sender as GridView; if (view != null ) { // 获取当前单元格的值 var cellValue = view.GetRowCellValue(e.RowHandle1, fieldName); // 获取前一行相同列的单元格的值 var prevCellValue = view.GetRowCellValue(e.RowHandle2, fieldName); if (e.RowHandle2 >= 0 && cellValue != null && cellValue.Equals(prevCellValue)) { // 合并单元格 e.Merge = true ; e.Handled = true ; } } } else { e.Merge = false ; e.Handled = true ; } }
我们可以根据自己的业务需要,设置一些合并的字段,放在列表中即可。呈现的界面效果类似下面所示.
这里值得注意的时候,如果我们需要把列表设置为具有复选框的记录显示模式,方便勾选来进行其他操作,那么就需要取消合并的功能。 。
this .gridView1.OptionsView.AllowCellMerge = false ;
这样才可以进行展示复选框的处理.
。
汇总的处理,也是类似的操作,需要设置显示底部的面板,以及设置好汇总列的处理信息.
。
为了更方便的设置统计信息,我们可以建立一个扩展函数的方式,来实现统计行的信息处理,如下扩展方法所示.
/// <summary> /// 设置统计列内容 /// </summary> /// <param name="gridView"> GridView对象 </param> /// <param name="fieldName"> 统计字段 </param> /// <param name="summaryItemType"> 统计类型 </param> /// <param name="prefix"> 显示前缀 </param> public static void SetSummaryColumn( this GridView gridView, string fieldName, SummaryItemType summaryItemType = SummaryItemType.Sum, string prefix = "" ) { if (! gridView.OptionsView.ShowFooter) { gridView.OptionsView.ShowFooter = true ; } if (gridView.Columns.Count > 0 ) { gridView.Columns[fieldName].SummaryItem.FieldName = fieldName; gridView.Columns[fieldName].SummaryItem.DisplayFormat = gridView.Columns[fieldName].DisplayFormat.FormatString; gridView.Columns[fieldName].SummaryItem.SummaryType = summaryItemType; gridView.Columns[fieldName].SummaryItem.DisplayFormat = prefix + " {0} " ; } }
如果我们需要在创建统计行的时候,请空它之前的记录信息,那么也可以增加多一个扩展函数来处理清空统计信息,如下所示.
/// <summary> /// 清空统计项目 /// </summary> /// <param name="gridView"></param> public static void ClearSummaryColumns( this GridView gridView) { gridView.OptionsView.ShowFooter = false ; foreach (GridColumn column in gridView.Columns) { if (column.SummaryItem != null ) { column.SummaryItem.Collection.Clear(); } } }
最终我们在界面上创建统计信息的代码如下所示.
// 添加统计行 gridView1.ClearSummaryColumns(); gridView1.SetSummaryColumn( " 订单量 " , DevExpress.Data.SummaryItemType.Sum); gridView1.SetSummaryColumn( " 完成数量 " , DevExpress.Data.SummaryItemType.Sum);
最终的界面效果如下所示 。
。
有时候为了更加便捷的对记录信息进行复制或者粘贴到GridView列表中进行处理,那么需要设置相关的GridView的属性,让它能够允许复制并设置复制的信息,这样的格式化后,就可以用于粘贴到记事本或者粘贴到新增记录模式下的GridView视图中了.
我们只需要设置其中的OptionsClipboard中的某些属性,如下代码所示.
// 实现选择复制到新的行中 view.OptionsClipboard.AllowCopy = DefaultBoolean.True; // 允许复制 view.OptionsClipboard.CopyColumnHeaders = DefaultBoolean.False; // 是否复制表头 view.OptionsClipboard.PasteMode = DevExpress.Export.PasteMode.Append; // 粘贴模式 view.OptionsClipboard.ClipboardMode = DevExpress.Export.ClipboardMode.Formatted; // 格式化模式
然后,如果我们的GridView是设置到编辑模式的话,设置下面的代码,让它可以新增粘贴的记录.
view.OptionsBehavior.Editable = true ; view.OptionsBehavior.ReadOnly = false ; view.OptionsBehavior.AllowAddRows = true ;
设置好这些,我们如果需要从剪切板中粘贴记录过来,那么只需要简单的饿调用下即可.
view.PasteFromClipboard(); // 从剪切板中复制记录过来
如果需要从Excel里面导入到记录表里面我们只需要读取Excel里面的记录,然后设置到当前的列表中即可.
var fileDialog = new OpenFileDialog(); fileDialog.Title = " 导入xcel " ; fileDialog.Filter = " Excel文件(*.xls)|*.xls " ; var dialogResult = fileDialog.ShowDialog( this ); if (dialogResult == DialogResult.OK) { ExcelImporter.ImportExcel(fileDialog.FileName, currentView); }
。
GridView本身控件提供了ExportToXls、ExportToXlsx两个方法,可以直接把数据导出为Excel文件,可以指定常规的xls或者xlsx的格式.
如下代码所示.
var fileDialog = new SaveFileDialog(); fileDialog.Title = " 导出Excel " ; fileDialog.Filter = " Excel文件(*.xls)|*.xls " ; var dialogResult = fileDialog.ShowDialog( this ); if (dialogResult == DialogResult.OK) { var options = new XlsExportOptions(); options. TextExportMode = TextExportMode.Text; // 修改绑定数据的格式为文本 view. ExportToXls (fileDialog.FileName); MessageDxUtil.ShowTips( " 导出Excel成功! " ); if (openExcel && File.Exists(fileDialog.FileName)) { System.Diagnostics.Process.Start(fileDialog.FileName); } }
当然,我们也可以利用第三方控件Aspose.Cell或者NPOI、Myxls的控件进行Excel的导出操作,那样也可以提供更多通用的控制处理.
自定义格式的报表导出,可以是一个典型的图文并茂的统计报表,类似样式如下所示.
如我在随笔《 使用Aspose.Cell控件实现Excel高难度报表的生成(一) 》、《 使用Aspose.Cell控件实现Excel高难度报表的生成(二) 》、《 利用Aspose.Word控件和Aspose.Cell控件,实现Word文档和Excel文档的模板化导出 》中介绍过相关的处理方式,一般我们使用封装好的方法,通用的导出Excel内容即可,有时候我们直接利用分页控件进行封装,导出常规的Excel文档.
AsposeExcelTools.DataTableToExcel2(table, (String)e.Argument,
out
outError);
导出Excel数据的效果如下所示.
。
GridView本身也提供了直接打印的操作方法,如果对一些简单的表格,可以直接使用它进行打印当前视图处理.
currentView.GridControl.ShowRibbonPrintPreview();
这样的打印效果,呈现出一个Ribbon的报表预览界面,然后直接在上面进行定制打印的格式.
或者我们也可以在生成打印预览的时候,指定更多的定制信息,如下界面所示.
private void menu_PrintFixColumn_Click( object sender, EventArgs e) { this .winGridViewPager1.gridView1.OptionsPrint.EnableAppearanceEvenRow = true ; using (PrintableComponentLink link = new PrintableComponentLink( new PrintingSystem())) { link.Component = this .winGridViewPager1.gridControl1; link.Landscape = true ; link.PaperKind = System.Drawing.Printing.PaperKind.A3; link.CreateMarginalHeaderArea += new CreateAreaEventHandler(Link_CreateMarginalHeaderArea); link.CreateDocument(); link.ShowPreview(); } } private void Link_CreateMarginalHeaderArea( object sender, CreateAreaEventArgs e) { string title = this .AppInfo.AppUnit + " -- " + " 备件信息报表 " ; PageInfoBrick brick = e.Graph.DrawPageInfo(PageInfo.None, title, Color.DarkBlue, new RectangleF( 0 , 0 , 100 , 21 ), BorderSide.None); brick.LineAlignment = BrickAlignment.Center; brick.Alignment = BrickAlignment.Center; brick.AutoWidth = true ; brick.Font = new System.Drawing.Font( " 宋体 " , 11f, FontStyle.Bold); }
类似的打印预览的界面效果如下所示.
当然我们也可以利用第三方控件的打印处理来实现更多的效果,不过内置的GridView打印操作,基本上也能满足大多数的要求了.
。
GridView的右键菜单,可以用ContextMenuStrip的常规性菜单控件来定义,我分页控件中就是采用这样的方式,设置比较简单,只需要设置GridCtrol控件的ContextMenuStrip属性即可,如下代码所示.
this .gridControl1.ContextMenuStrip = this .contextMenuStrip1;
并且通过ContextMenuStrip的Opening事件,可以对它进行一定的设置禁用/可用的处理.
this .contextMenuStrip1.Opening += new CancelEventHandler(contextMenuStrip1_Opening); private void contextMenuStrip1_Opening( object sender, CancelEventArgs e) { this .menu_Add.Visible = ( this .OnAddNew != null && this .ShowAddMenu); this .menu_Delete.Visible = ( this .OnDeleteSelected != null && this .ShowDeleteMenu); this .menu_Edit.Visible = ( this .OnEditSelected != null && this .ShowEditMenu); this .menu_Refresh.Visible = ( this .OnRefresh != null ); }
这样就可以对GridView的右键进行绑定及权限的设置处理,类似下面的界面效果所示.
虽然利用ContextMenuStrip的传统菜单条,可以很好、方便的实现右键菜单的处理,不过缺点是样式没有随着DevExpress本身的效果变化,如果需要追求一样的样式体验,那么可以考虑使用DevExpress的PopupMenu控件来承载菜单或者Ribbon的一些按钮操作.
PopupMenu控件可以指定Ribbon窗体控件,然后它们右键菜单和Ribbon的按钮集合同样的出现和隐藏.
然后在设计模式下设计对应的菜单项目集合.
在界面设计好Ribbon的按钮和菜单对象的按钮后,我们可以为菜单绑定对应的GridControl事件处理,让它结合GridControl的右键事件出现右键菜单.
this
.gridControl.MouseUp += GridControl_MouseUp;
显示右键菜单的事件代码如下所示.
private void GridControl_MouseUp( object sender, MouseEventArgs e) { try { if (e.Button == MouseButtons.Right) { var view = gridControl.DefaultView as GridView; var info = view.CalcHitInfo(e.Location); if (info.InRowCell) { popupGridMenu.ShowPopup(gridControl.PointToScreen(e.Location)); } } } catch (Exception ex) { MessageDxUtil.ShowError(ex.Message); } }
。
之前在随笔《 在DevExpress程序中使用GridView直接录入数据的时候,增加列表选择的功能 》 、《 在DevExpress程序中使用Winform分页控件直接录入数据并保存 》分别介绍了两种不同方式的数据直接在GridView列表中处理的方式,本质上两者是一致的,都是利用GridView本身的一些事件进行操作,实现更加方便的数据录入体验.
我们一般通过 InitNewRow 、ValidateRow 、CellValueChanged来处理数据的录入操作,如下详细操作的界面代码所示.
private void RegisterEvent() { var grd = this .gridControl1; var grv = this .gridView1; grv.InitGridView(GridType.NewItem, false , EditorShowMode.MouseDownFocused, "" ); // 创建显示的列 grv.CreateColumn( " ItemNo " , " 备件编号 " , 120 ).CreateButtonEdit().ButtonClick += (s, e) => { #region 选取备件信息,返回后赋值当前记录 if (grv.GetFocusedRow() == null ) { grv.AddNewRow(); // 一定要增加 } FrmSelectItemDetail dlg = new FrmSelectItemDetail(); dlg.WareHouse = this .txtWareHouse.Text; if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { var info = dlg.ItemDetailInfo; if (info != null ) { grv.SetFocusedRowCellValue( " ItemNo " , info.ItemNo); grv.SetFocusedRowCellValue( " ItemName " , info.ItemName); grv.SetFocusedRowCellValue( " ItemBigType " , info.ItemBigType); grv.SetFocusedRowCellValue( " ItemType " , info.ItemType); grv.SetFocusedRowCellValue( " MapNo " , info.MapNo); grv.SetFocusedRowCellValue( " Specification " , info.Specification); grv.SetFocusedRowCellValue( " Unit " , info.Unit); grv.SetFocusedRowCellValue( " Price " , info.Price); grv.SetFocusedRowCellValue( " Material " , info.Material); grv.SetFocusedRowCellValue( " Source " , info.Source); grv.SetFocusedRowCellValue( " StoragePos " , info.StoragePos); grv.SetFocusedRowCellValue( " UsagePos " , info.UsagePos); grv.SetFocusedRowCellValue( " WareHouse " , info.WareHouse); grv.SetFocusedRowCellValue( " Dept " , info.Dept); grv.SetFocusedRowCellValue( " Quantity " , 1 ); // 默认数量为1 } } #endregion }; grv.CreateColumn( " ItemName " , " 备件名称 " , 120 ); grv.CreateColumn( " Quantity " , " 数量 " ).CreateSpinEdit(); grv.CreateColumn( " ItemBigType " , " 备件属类 " , 120 ); grv.CreateColumn( " ItemType " , " 备件类别 " , 120 ); grv.CreateColumn( " MapNo " , " 图号 " ); grv.CreateColumn( " Specification " , " 规格型号 " , 120 ); grv.CreateColumn( " Unit " , " 单位 " ); grv.CreateColumn( " Price " , " 单价 " ); grv.CreateColumn( " Amount " , " 金额 " ); grv.CreateColumn( " Material " , " 材质 " , 120 ); grv.CreateColumn( " Source " , " 来源 " , 120 ); grv.CreateColumn( " StoragePos " , " 库位 " , 120 ); grv.CreateColumn( " UsagePos " , " 使用位置 " , 120 ); grv.CreateColumn( " WareHouse " , " 所属库房 " , 120 ); grv.CreateColumn( " Dept " , " 所属部门 " , 120 ); // 设置部分字段不可修改 var readonlyFields = " ItemName,ItemBigType,ItemType,MapNo,Specification,Unit,Price,Amount,Material,Source,UsagePos,WareHouse,Dept " ; grv.SetColumnsReadOnly(readonlyFields); // 绑定数据源,否则无法新增存储 var list = new List<ItemDetailInfo> (); var dt = DataTableHelper.ConvertToDataTable<ItemDetailInfo> (list); // 同时增加两列在实体类属性里没有的列 dt.Columns.Add( new DataColumn( " Quantity " , typeof ( int ))); dt.Columns.Add( new DataColumn( " Amount " , typeof ( decimal ))); grd.DataSource = dt; grv.InitNewRow += delegate ( object sender, InitNewRowEventArgs e) { // 如果是GUID的主键,可以初始化,以及赋值明细记录的父ID等操作 // GridView gridView = grd.FocusedView as GridView; // gridView.SetFocusedRowCellValue("ID", Guid.NewGuid().ToString()); }; grv.ValidateRow += delegate ( object sender, ValidateRowEventArgs e) { // 校验一些不能为空的字段 var result = grd.ValidateRowNull(e, new string [] { " ItemNo " , " ItemName " , " Quantity " }); }; grv.CellValueChanged += ( object sender, CellValueChangedEventArgs e) => { // 根据数量计算金额 if (e.Column.FieldName == " Quantity " && e.Value != null ) { var Price = string .Concat(grv.GetFocusedRowCellValue( " Price " )).ToDecimal(); var Quantity = string .Concat(e.Value).ToDecimal(); grv.SetFocusedRowCellValue( " Amount " , Price * Quantity); } }; grv.RowCellStyle += ( object sender, RowCellStyleEventArgs e) => { // 设置特殊颜色标志 if (e.Column.FieldName == " Quantity " ) { e.Appearance.BackColor = Color.Moccasin; e.Appearance.ForeColor = Color.Red; } }; }
而如果需要结合删除的功能,那么可以增加对RowDeleted的事件处理.
// 行删除操作 grv.OptionsBehavior.AllowDeleteRows = DefaultBoolean.True; grv.RowDeleted += (s, ee) => { // 同时移除价格列表 var info = ee.Row as OrderInfo; if (info != null ) { this .OrderInfos.Remove(info); for ( int i = 0 ; i < this .gridView2.RowCount; i++ ) { var code = ( string ) this .gridView2.GetRowCellValue(i, " 产品编码 " ); if (info.产品编码 == code) { this .gridView2.DeleteRow(i); } } } }; grv.KeyDown += (s, ee) => { if (ee.KeyCode == Keys.Delete) { gridView1.DeleteSelectedRows(); ee.Handled = true ; } };
以上就是在实际项目中,常用到的GridControl和GridView的常规处理方法,用好这些控件的处理,可以极大程度的提高用户的界面体验.
当然可能还有很多常用的方法或者处理方式,等待大家的进一步挖掘和分享.
最后此篇关于基于DevExpress的GridControl实现的一些界面处理功能的文章就讲到这里了,如果你想了解更多关于基于DevExpress的GridControl实现的一些界面处理功能的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我是一家小型非营利组织的技术总监,我们正在制作一个新网站。我们提出了几个不同主页设计的模型,需要接收董事会成员的意见。是否有在线应用程序/程序/框架可以接收和组织用户评论?我正在寻找允许在查看页面时发
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我阅读了很多关于 java 接口(interface)的文章。我知道你可以实现多态性和其他伟大的东西(函数指针等)。我有理论知识,但有一点点或什至没有。我一直在使用很多已经制作好的界面,比如“Runn
已关闭。此问题旨在寻求有关书籍、工具、软件库等的建议。不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以
我正在尝试在 Windows 7 上编写一个 python 脚本来与我的 Wacom Bamboo Pen 数位板交互。 Wacom 建议使用 WinTab API,它工作正常,但不适用于我的应用程序
我正在研究一种远程访问有关 Linux 服务器统计信息的方法,即 conky会显示。 有没有办法与 conky 交互并获取它显示的统计信息?如果没有,您能否推荐一种获取此类统计数据的好方法? (C/C
将所有这些代码包装在 UI: do { } block 中的原因是什么?我在哪里可以获得关于它的明确说明? UI: do { backgroundButton.setImage(UIImage
我需要将 R 连接到某些 C# 应用程序。我安装了 rscproxy_1.3 和 R_Scilab_DCOM3.0-1B5 添加了对 STATCONNECTORCLNTLib、StatConnecto
我正在尝试遍历接口(interface)片段以通过 id 查找我的特定结构并更改属性。 type A struct { ID ID Steps []Step } type Ste
我有两种不同格式的相同界面,一种是键由低破折号分隔的 JSON 格式,另一种是 javascript camelCase 格式: JSON 格式: interface MyJsonInterface
操作系统:Linux。 我正在尝试寻找可能的方法来为我的嵌入式系统实现 Web 界面。 目前有一个外壳(基于文本)和一小组命令用于查询设备。 我是网络开发新手,我的问题是: 我必须使用什么网络服务器?
我正在尝试运行基于 Mechanical Turk Qualtrics 的调查,并且需要一些似乎可以通过 Mechanical Turk API 使用的功能,例如 custom Qualificati
我见过漂亮的 MetroTwit 界面 http://www.metrotwit.com/ ;我想知道使用了哪些 WPF 组件来尝试重现它。 最佳答案 MetroTwit 设计师在这里:) 所有的控件
我有一个小问题。我需要将 Hadoop Web 界面与我们的 Web 应用程序集成。我只需要一个 Hadoop 接口(interface),我们可以在其中运行一些 hadoop 命令,例如 1
假设我有这个 JavaScript 函数: function updateMainBuff(buff) { // do some stuff } 我的
我试图找出一个窗口是否属于当前的虚拟桌面。 我从 winapi 中找到了 VirtualDesktopManager 类,但即使根据 here 它应该位于“shobjidl.h” header 中,当
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 8年前关闭。 Improve this
我的 Tkinter GUI 界面有问题。文本不会在 shell 中打印,但如果将 Entry 放置在第一个 tk 窗口 get() 中,它就可以工作...帮助我吗? 这是我的代码: import o
我有一个在 MATLAB 中实现的随机微分方程组。只有 4 个变量与 Euler-Maruyama 集成,所以没有什么太花哨的......不过,技术细节对于这个问题并不重要。 您建议我如何构建一个 W
对于我创建的插件,我想添加一个网络界面,您可以从中更改设置并执行一些简单的数据操作。此数据操作应通过 sqlquerys 完成。我正在使用 sqlite 数据库,这就是问题开始的地方: 网站(serv
我是一名优秀的程序员,十分优秀!