基于DevExpress的GridControl实现的一些界面处理功能
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实现的一些界面处理功能的更多相关文章
- DevExpress的GridControl的实时加载数据解决方案(取代分页)
http://blog.csdn.net/educast/article/details/4769457 evExpress是一套第三方控件 其中有类似DataGridView的控件 今天把针对Dev ...
- 总结开发中基于DevExpress的Winform界面效果
DevExpress是一家全球知名的控件开发公司, DevExpress 也特指此公司出品的控件集合或某系列控件或其中某控件.我们应用最为广泛的是基于Winform的DevExpress控件组,本篇随 ...
- 基于DevExpress的BandedGridView动态生成多行(复合)表头
最近cs项目中有个看板的功能需求,整个系统是基于DevExpress组件开发的,由于对这个组件的布局不是很熟,也借鉴了网上一些其他人的做法,普遍都是通过GridControl的BandedGridVi ...
- 基于DevExpress的Winform程序安装包的制作
在我们做系统开发的时候,都会面临一个安装包制作的问题,如何把我们做好的系统,通过安装包工具整合成一个安装包给客户进行安装.安装包的优势就是一步步安装就可以了,不用复制一大堆文件给客户,还怕缺少那个文件 ...
- DevExpress内 GridControl中复选框值问题
在DevExpress的 GridControl内的复选柜勾选后,界面看到是勾选状态,但对应的DataView的值仍未变,在以下事件内处理 在对应的DataView内的 CellValueChangi ...
- DevExpress之GridControl控件小知识
DevExpress之GridControl控件小知识 一.当代码中的DataTable中有建数据关系时,DevExpress 的 GridControl 会自动增加一个子视图 .列名也就是子表的字段 ...
- DevExpress.XtraGrid.GridControl 实现自定义tooltip
DevExpress.XtraGrid.GridControl 控件默认的tooltip显示的每一个单元格的文本值,但是实际工作中会出现各种需求.我这里就有一个列是折扣率显示的值是0-1之间的两位小数 ...
- C# DevExpress 的gridControl或gridView数据导出失败解决方法
来自:http://blog.csdn.net/lybwwp/article/details/8049464 谢谢 在使用DevExpress 的GridPanel控件的时候出现了一个莫名其妙的现象, ...
- DevExpress的GridControl控件更新數據問題解決辦法
開發WPF程序時,使用Devexpress的GridControl控件用ItemSource綁定數據,在頁面進行編輯時,當屬性繼承INotifyPropertyChanged接口時會同步更新後臺數據. ...
- devexpress表格gridcontrol实现分组,并根据分组计算总计及平均值
1.devexpress表格控件gridcontrol提供了强大的分组功能,你几乎不用写什么代码就可以实现一个分组功能,并且可根据分组计算总计和平均值.这里我例举了一个实现根据班级分组计算班级总人数, ...
随机推荐
- 论文解读(ToAlign)《ToAlign: Task-oriented Alignment for Unsupervised Domain Adaptation》
论文信息 论文标题:ToAlign: Task-oriented Alignment for Unsupervised Domain Adaptation论文作者:Guoqiang Wei, Cuil ...
- GO语言学习笔记-包结构篇 Study for Go ! Chapter eight - Package Structure
持续更新 Go 语言学习进度中 ...... GO语言学习笔记-类型篇 Study for Go! Chapter one - Type - slowlydance2me - 博客园 (cnblogs ...
- Spring--第三方bean管理
第三方bean管理 管理第三方的bean的话,是不能在配置文件里面写这个注解的: 他表示的是,扫描你当前文件里面的bean,是可以直接获取到的. 那么,对于第三方的bean,我们可以这么做: 在配置文 ...
- 关于IDEA新建Maven项目时,会卡死,无法实现新建问题的具体解决
对于问题的描述 在进行新建项目时,突然就出现了选择好一切之后,点击CREATE后,直接卡死停滞(对于一个菜菜来说,只能通过电脑重启来改变一下它无法动弹的状态了) 对于该问题的解决 解决的话,具体步骤如 ...
- Linux0.11源码学习(二)
Linux0.11源码学习(二) linux0.11源码学习笔记 参考资料:https://github.com/sunym1993/flash-linux0.11-talk 源码查看:https:/ ...
- 前后端分离项目,配置问题导致后端session丢失问题
今天遇到一个巨坑,后端写了获取验证码接口,以及验证验证码接口 获取验证码接口: /// <summary> /// 获取验证码 /// </summary> /// <r ...
- ZIP64压缩扩展的兼容性问题
一.ZIP压缩的两种规范 zip64 格式是标准 zip 格式的扩展,实际上消除了 zip 存档中文件大小和数量的限制. 每种格式允许的最大值总结如下: Standard Format Zip64 F ...
- Debiased Contrastive Learning of Unsupervised Sentence Representations 论文精读
1. 介绍(Introduction) 问题: 由PLM编码得到的句子表示在方向上分布不均匀, 在向量空间中占据一个狭窄的锥形区域, 这在很大程度上限制了它们的表达能力. 已有的解决办法: 对比学习. ...
- 机器学习系列入门系列[七]:基于英雄联盟数据集的LightGBM的分类预测
1. 机器学习系列入门系列[七]:基于英雄联盟数据集的LightGBM的分类预测 1.1 LightGBM原理简介 LightGBM是2017年由微软推出的可扩展机器学习系统,是微软旗下DMKT的一个 ...
- ASP.NET Core - 选项系统之选项验证
就像 Web Api 接口可以对入参进行验证,避免用户传入非法的或者不符合我们预期的参数一样,选项也可以对配置源的内容进行验证,避免配置中的值与选项类中的属性不对应或者不满足预期,毕竟大部分配置都 ...