DevExpress的GridControl控件能够提供很多强大的操作,其视图GridView能够通过各种设置,呈现出多种复杂的界面效果,本篇随笔探讨一些常见的GridControl控件及其GridView的视图操作处理,以便在大家也需要的时候作为一个参考的代码。其中设计一些常见的操作,如合并单元格、汇总统计、复制粘贴行、导入数据处理、导出Excel、导出PDF等、打印GridView视图、内置插入及保存数据处理等等。

1、合并单元格

有时候,需要把多行紧挨着的单元格内容进行合并展示,这样有助于界面的美观及查看便利,如下界面所示。

或者这样的界面,都是类似的效果。

合并的处理比较简单,只需要设置允许合并,以及实现合并的处理事件代码即可。

    //允许合并
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;

这样才可以进行展示复选框的处理。

2、汇总统计处理

汇总的处理,也是类似的操作,需要设置显示底部的面板,以及设置好汇总列的处理信息。

为了更方便的设置统计信息,我们可以建立一个扩展函数的方式,来实现统计行的信息处理,如下扩展方法所示。

/// <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);

最终的界面效果如下所示

3、复制粘贴行及导入处理

有时候为了更加便捷的对记录信息进行复制或者粘贴到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);
}

4、内置的导出Excel处理及导出PDF操作

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数据的效果如下所示。

5、打印当前GridView视图

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打印操作,基本上也能满足大多数的要求了。

6、弹出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);
}
}

7、直接新增保存的处理

之前在随笔《在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实现的一些界面处理功能的更多相关文章

  1. DevExpress的GridControl的实时加载数据解决方案(取代分页)

    http://blog.csdn.net/educast/article/details/4769457 evExpress是一套第三方控件 其中有类似DataGridView的控件 今天把针对Dev ...

  2. 总结开发中基于DevExpress的Winform界面效果

    DevExpress是一家全球知名的控件开发公司, DevExpress 也特指此公司出品的控件集合或某系列控件或其中某控件.我们应用最为广泛的是基于Winform的DevExpress控件组,本篇随 ...

  3. 基于DevExpress的BandedGridView动态生成多行(复合)表头

    最近cs项目中有个看板的功能需求,整个系统是基于DevExpress组件开发的,由于对这个组件的布局不是很熟,也借鉴了网上一些其他人的做法,普遍都是通过GridControl的BandedGridVi ...

  4. 基于DevExpress的Winform程序安装包的制作

    在我们做系统开发的时候,都会面临一个安装包制作的问题,如何把我们做好的系统,通过安装包工具整合成一个安装包给客户进行安装.安装包的优势就是一步步安装就可以了,不用复制一大堆文件给客户,还怕缺少那个文件 ...

  5. DevExpress内 GridControl中复选框值问题

    在DevExpress的 GridControl内的复选柜勾选后,界面看到是勾选状态,但对应的DataView的值仍未变,在以下事件内处理 在对应的DataView内的 CellValueChangi ...

  6. DevExpress之GridControl控件小知识

    DevExpress之GridControl控件小知识 一.当代码中的DataTable中有建数据关系时,DevExpress 的 GridControl 会自动增加一个子视图 .列名也就是子表的字段 ...

  7. DevExpress.XtraGrid.GridControl 实现自定义tooltip

    DevExpress.XtraGrid.GridControl 控件默认的tooltip显示的每一个单元格的文本值,但是实际工作中会出现各种需求.我这里就有一个列是折扣率显示的值是0-1之间的两位小数 ...

  8. C# DevExpress 的gridControl或gridView数据导出失败解决方法

    来自:http://blog.csdn.net/lybwwp/article/details/8049464 谢谢 在使用DevExpress 的GridPanel控件的时候出现了一个莫名其妙的现象, ...

  9. DevExpress的GridControl控件更新數據問題解決辦法

    開發WPF程序時,使用Devexpress的GridControl控件用ItemSource綁定數據,在頁面進行編輯時,當屬性繼承INotifyPropertyChanged接口時會同步更新後臺數據. ...

  10. devexpress表格gridcontrol实现分组,并根据分组计算总计及平均值

    1.devexpress表格控件gridcontrol提供了强大的分组功能,你几乎不用写什么代码就可以实现一个分组功能,并且可根据分组计算总计和平均值.这里我例举了一个实现根据班级分组计算班级总人数, ...

随机推荐

  1. Glist 按钮属性

    grayed 变灰与否不影响点击等事件 touchable 为false,不会变灰,但会无法点击, enabled为false自动变灰,且无法点击

  2. 一文带你了解 JS Module 的始末

    写在前面 模块化开发是我们日常工作潜移默化中用到的基本技能,发展至今非常地简洁方便,但开发者们(指我自己)却很少能清晰透彻地说出它的发展背景, 发展过程以及各个规范之间的区别.故笔者决定一探乾坤,深入 ...

  3. Linux & 标准C语言学习 <DAY7>

    一.windows下获取方向键:     1.导入#include <conio.h>     2.通过getch()获取键盘上的键值         上:72  下:80  左:75   ...

  4. 【WEB UI自动化】Selenium爬取用户的知乎回答时遇到10002:请求参数异常,请升级客户端后重试

    这里分享一个低配版知乎爬虫,利用了Selenium模块 爬取的过程中遇到了10002:请求参数异常,请升级客户端后重试,调用知乎某用户的回答API返回的HTTP状态码是403 Forbidden 之后 ...

  5. js函数防抖节流

    // 3.1 函数防抖: // 当持续触发事件时,一定时间段内没有再次触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时.// 也就是说当一个用户一直触发这个函数, ...

  6. 更优雅的OrientDB Java API

    OrientDB API v1.0.0(OrientDB 3.x) Gitee OrientDB介绍 OrientDB是一个开源的NoSQL数据库管理系统,同时也是一款高性能的图数据库,支持ACID事 ...

  7. 基于开源的 ChatGPT Web UI 项目,快速构建属于自己的 ChatGPT 站点

    作为一个技术博主,了不起比较喜欢各种折腾,之前给大家介绍过 ChatGPT 接入微信,钉钉和知识星球(如果没看过的可以翻翻前面的文章),最近再看开源项目的时候,发现了一个 ChatGPT Web UI ...

  8. 浅谈ChatGPT如何取代前端开发工程师

    1.ChatGPT 是什么? ChatGPT 是一种基于深度学习的自然语言处理技术,它可以生成高质量的自然语言文本.该技术是由 OpenAI 团队 开发,旨在使计算机能够像人类一样理解和产生自然语言. ...

  9. MySQL explain 和 profiling 详解

    MySQL explain 和 profiling 详解 mysql explain MySQL 的 EXPLAIN 是一个用于查询优化的工具,它可以显示 MySQL 数据库如何执行查询.它返回一组关 ...

  10. [GAUSS-50201]:The /opt/software/openGauss/xxxx-RedHat-64bit.tar.bz2 does not exist

    问题描述:使用redhat7.9来安装opengauss集群,预安装过不去.opengauss官方只支持centos版本,最好是centos7.6. [root@db01 script]# ./gs_ ...