玩转控件:对Dev的GridControl控件扩展

缘由

     一切实现来源于需求,目的在于不盲目造轮子,有小伙伴儿在看了《玩转控件:对Dev中GridControl控件的封装和扩展》文章后,私信作者说,因公司业务逻辑比较复杂,展示字段比较多,尤其网格列表控件展示数据太多时候,很多关键列信息不同用户要求展示效果不同,问我有没有好点的处理方式来满足不同客户的需求。

    看到这里作者还是比较暗自窃喜的,毕竟自己造的轮子不止作者一个人在用,而且还能收获客户的实际需求来完善轮子。当然客户需求存在即合理。毕竟There are a thousand Hamlets in a thousand people's eyes.

何以解忧唯有撸码

    有了需求,眼球一转,就撸起袖子加油干吧。初步想法直接在《玩转控件:对Dev中GridControl控件的封装和扩展》的基础上,右键菜单网格设置状态里面处理吧。把处理后的结果通过配置文件方式(ini,xml...)存储起来,网格加载的时候,通过校验是否存在配置文件来加载不同客户的配置信息即可。    有了想法,就行动起来吧!气运丹田,双手摊开,扎下马步,使出"拖控件大法"一气呵成!

    大致需求与实现如上图,本来还有列中文列名的,但是客户说不要~~(如有更多不同需求或更好的想法,请自行添加或者公众号私信作者一起探讨),

Talk is Cheap,Show me the Code

    跟用户反复沟通,具体效果图如上,下面一起看看是如何实现的。

    思路:网格表格右键点击网格状态设置,弹出如上设置窗体,窗体界面加载的时候绑定GridControl所有数据列,并在保存时候存储到配置文件中,具体代码如下:

  /// <summary>/// 数据加载初始化/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void frm_GridSetting_Load(object sender, EventArgs e){//读取配置文件,更新网格状态string sPath = $@"{ Application.StartupPath}\Task.xml";DataTable dtColumns = this.gc.DataSource as DataTable;GridView gvv = gc.MainView as GridView; if (dtColumns != null && dtColumns.Rows.Count > 0){DataTable dtSetting = new DataTable("GridSetting");dtSetting.Columns.Add("ColumnsName", typeof(String));dtSetting.Columns.Add("isDisplay", typeof(Boolean));dtSetting.Columns.Add("Freeze", typeof(String));dtSetting.Columns.Add("ColumnsWidth", typeof(Int32));dtSetting.Columns.Add("Order1", typeof(String));dtSetting.Columns.Add("Order2", typeof(String));dtSetting.Columns.Add("Top", typeof(String));dtSetting.Columns.Add("Button", typeof(String));dtSetting.Columns.Add("iOrder", typeof(Int32));if (!File.Exists(sPath)){ for (int i = 0; i < gvv.VisibleColumns.Count; i++){string colName = gvv.VisibleColumns[i].Name.Replace("col", "");dtSetting.Rows.Add(new object[] { colName, true, "无", 120, "上移", "下移", "置顶", "置底", gvv.VisibleColumns[i].VisibleIndex });}}else{//读取XML 绑定数据源XDocument xdoc = XDocument.Load(sPath);var query = from a in xdoc.Descendants("Columns")select new{ColumnsName = a.Attribute("ColumnsName").Value,isDisplay = a.Element("isDisplay").Value,Freeze = a.Element("Freeze").Value,ColumnsWidth = a.Element("ColumnsWidth").Value,iOrder = a.Element("iOrder").Value};int index = 0;foreach (var item in query.ToList()){dtSetting.Rows.Add(new object[] { item.ColumnsName, Boolean.Parse(item.isDisplay), item.Freeze, int.Parse(item.ColumnsWidth), "上移", "下移", "置顶", "置底", index });index++;//排序重置}}gcSetting.DataSource = dtSetting;repositoryItemButtonEdit1.ButtonClick += RepositoryItemButtonEdit1_ButtonClick;//上移 repositoryItemButtonEdit2.ButtonClick += RepositoryItemButtonEdit2_ButtonClick;//下移 repositoryItemButtonEdit3.ButtonClick += RepositoryItemButtonEdit3_ButtonClick;//置顶 repositoryItemButtonEdit4.ButtonClick += RepositoryItemButtonEdit4_ButtonClick;//置底 }}

    网格窗体点击确认,用来保存用户的配置信息:

 /// <summary>
/// 确定
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSure_Click(object sender, EventArgs e)
{try{//保存动作string sPath = $@"{ Application.StartupPath}\Task.xml";loop:if (!File.Exists(sPath)){File.Create(sPath).Close();XDocument xdoc = new XDocument();//创建跟节点XElement root = new XElement("Mes");//添加跟节点xdoc.Add(root);DataTable dtSetting = gcSetting.DataSource as DataTable;int index = 0;foreach (DataRow item in dtSetting.Rows){//创建person节点 XElement per = new XElement("Columns");//添加person节点root.Add(per);//创建属性节点XAttribute ColumnsName = new XAttribute("ColumnsName", item["ColumnsName"].ToString());//name节点XElement isDisplay = new XElement("isDisplay", item["isDisplay"].ToString());XElement Freeze = new XElement("Freeze", item["Freeze"].ToString());XElement ColumnsWidth = new XElement("ColumnsWidth", item["ColumnsWidth"].ToString());XElement iOrder = new XElement("iOrder", index);//对person节点添加id属性 以及name sex age节点per.Add(ColumnsName, isDisplay, Freeze, ColumnsWidth, iOrder);index++;}//保存linq to xml 文件xdoc.Save(sPath);}else{File.Delete(sPath);goto loop;}//刷新原始界面显示if (RefreshMDIFormEvent != null){RefreshMDIFormEvent();}}catch (Exception ex){}finally{this.Close();}
}

    因最近项目上线,时间紧迫(吃饭时间写的博客)。作者就偷个懒,每次确认都会先删除配置文件,然后重新新增。实际项目中可以通过更新来处理。而且goto语法也比较low,大家将就着看下效果,具体更好实现,伙伴们可以自行重写。唯一值得注意的点是File文件流的问题,此处偷懒写法

File.Create(sPath).Close();

    防止保存配置文件的时候,提示文件被其他用户占用的问题。至于上移,下移,置顶,置底等功能网上很多示例,也可以公众号私聊作者,所有源码免费赠送。配置文件如图:

    配置界面梳理完毕,只需要在主窗体数据加载后,读取配置文件信息变更即可:

 kzxGridControl1.DataSource = dataTable;
GridView gv = this.kzxGridControl1.MainView as GridView;
//读取配置文件,更新网格状态
string sPath = $@"{ Application.StartupPath}\Task.xml";
if (File.Exists(sPath))
{XDocument xdoc = XDocument.Load(sPath);for (int i = 0; i < gv.Columns.Count; i++){string colName = gv.Columns[i].Name.Replace("col", "");var query = (from a in xdoc.Descendants("Columns")where a.Attribute("ColumnsName").Value == colNameselect new{isDisplay = a.Element("isDisplay").Value,Freeze = a.Element("Freeze").Value,ColumnsWidth = a.Element("ColumnsWidth").Value,iOrder = a.Element("iOrder").Value}).FirstOrDefault();if (query != null){gv.Columns[i].Visible = Boolean.Parse(query.isDisplay);if (query.Freeze.ToLower().Equals("无")){gv.Columns[i].Fixed = FixedStyle.None;}else if (query.Freeze.ToLower().Equals("左边")){gv.Columns[i].Fixed = FixedStyle.Left;}else if (query.Freeze.ToLower().Equals("右边")){gv.Columns[i].Fixed = FixedStyle.Right;}if (!Boolean.Parse(query.isDisplay)){gv.Columns[i].VisibleIndex = -1;gv.Columns[i].Visible = Boolean.Parse(query.isDisplay);}else{gv.Columns[i].VisibleIndex = int.Parse(query.iOrder);}gv.Columns[i].Width = int.Parse(query.ColumnsWidth);}}
}

    为了能实时更新配置效果,可在配置窗体添加个委托用于刷新主界面数据:

 public delegate void RefreshMDIFormHandler();
public event RefreshMDIFormHandler RefreshMDIFormEvent;
 /// <summary>
/// 网格状态设置
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void kzxSimpleButton2_Click(object sender, EventArgs e)
{frm_GridSetting frm = new frm_GridSetting(kzxGridControl1);frm.RefreshMDIFormEvent += Frm_RefreshMDIFormEvent;frm.ShowDialog();
}private void Frm_RefreshMDIFormEvent()
{this.frm_ShowControl_Load(null, null);
}

    时间紧急,处理的比较粗糙,直接调用load重新加载了。

    完成!所有实现处理完成,来一起看看效果:

            (效果原图)

(Email列置顶效果)

(TelePhone上移,确定后效果)

(隐藏列效果)

(设置列宽效果)

(列冻结效果)

(列冻结效果2)

    为了后续其他控件加载问题,本篇用按钮方式实现的弹窗,有需求的伙伴们可以把相关代码移动到GridContrl用户控件的右键菜单中实现。此处不在过多阐述。谢谢屏幕前您的耐心陪伴!

结束语

    由于后续所有重写/重绘控件都在同一个项目使用,而且Dev系统引用文件较多,压缩后源码文件仍然很大,如果有需要源码的朋友,可以微信公众号联系博主,源码可以免费赠予~!有疑问的也可以CALL我一起探讨。

        最后,感谢您的耐心陪伴!如果觉得本篇博文对您或者身边朋友有帮助的,麻烦点个关注!赠人玫瑰,手留余香,您的支持就是我写作最大的动力,感谢您的关注,期待和您一起探讨!再会!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310627.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二叉排序树(搜索树BST)-详解结点的删除

在二叉排序树中删除一个结点时&#xff0c;需保证删除后的二叉树仍然是二叉排序树。为讨论方便&#xff0c;假定被删除结点为p&#xff0c;其双亲结点为f。删除的过程可按下述的两种情况分别处理。 在这里我们用红色三角形表示我们要删除的结点&#xff0c;蓝色表示我们要改变指…

java调优方法,jvm监控工具

graph LR A-->B性能概述 程序性能表现形式 执行速度&#xff1a;程序响应速度&#xff0c;总耗时是否足够短内存分配&#xff1a;内存分配是否合理&#xff0c;是否过多消耗内存或者存在泄漏启动时间&#xff1a;程序运行到可以正常处理业务需要的时间负载承受能力 性能测…

那位五十多岁的创业者给我的启示!

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区特邀嘉宾&#xff01;一我曾经提到过最终改行从事美缝行业的老w&#xff0c;他靠自己的“不够努力”&#xff0c;最终离开了行业。但是&#xff0c;这个世界其实有点讽刺。在沉迷于安逸小日子的老…

平衡二叉树(AVL树)-详解平衡调整

平衡调整: (注意&#xff1a;平衡调整只是平衡调整&#xff0c;没有进行结点的插入) LL型调整: (带阴影的小框表示插入的结点) 代码如下: AVLNode *AVLTree::LL_Rotate(AVLNode *a) {AVLNode *b;b a->lchild;a->lchild b->rchild;b->rchild a;a->bf b-&g…

初识消息队列/RabbitMQ详解

欢迎大家阅读《朝夕Net社区技术专刊》我们致力于.NetCore的推广和落地&#xff0c;为更好的帮助大家学习&#xff0c;方便分享干货&#xff0c;特创此刊&#xff01;很高兴你能成为忠实读者&#xff0c;文末福利不要错过哦&#xff01;今天来给大家分享关于消息队列的内容&…

zookeeper理解

Zookeeper简介 Zookeeper的数据模型 层次化的目录结构&#xff0c;命名符合常规文件系统规范每个节点在zookeeper中叫做znode&#xff0c;并且有一个唯一的路径标识节点znode可以包含数据和子节点&#xff0c;但是EPHEMERAL类型的节点不能有子节点Znode中的互刷可以有多个版本…

那些年,在MSRA实习过的女孩,现在都怎么样了?

编者按&#xff1a;我们用两周时间回访了五位在 MSRA 实习过的女孩&#xff0c;她们也都是当年“实习派”的主人公。我们本想在更长的时间维度下&#xff0c;看一看 MSRA 给予她们的改变。然而超乎预期的是&#xff0c;在她们身上&#xff0c;坚持的力量比改变更强。变与不变&a…

Zookeeper理解---ZAB协议

ZAB协议 Zookeeper并不是完全采用Paxos算法&#xff0c;而是使用了一种称为Zookeeper Atomic Broadcast&#xff08;ZAB&#xff0c;Zookeeper原子消息广播协议&#xff09;作为数据一致性的核心算法&#xff0c;依据此算法来实现分布式数据一致性的解决。他是一种特别为Zooke…

【最强VSCode】之管理MySql数据库

(梅花香自苦寒来)你没有看错&#xff0c;就是用VSCode来管理MySql数据库&#xff0c;我也是第一次听说&#xff0c;感谢群管理DX小伙伴&#xff0c;三人行必有我师焉。话不多说&#xff0c;直接开张&#xff0c;VSCode还是很不错的&#xff0c;以后多多分享插件吧。1、你平时是…

[Flags]标识的Enum不能使用Html.GetEnumSelectList方法

在使用Asp.Net Core MVC写程序时&#xff0c;对用户类型做了如下定义&#xff1a;namespace ManufacturingExecutionSystemCore.Enums {public enum UserType{[Description("无身份人员")][Display(Name "无身份人员")]UnidentifiedPerson0x00,[Descripti…

Zookeeper实践与应用- Canal

基于MySql BinLog的增量订阅和消费组件&#xff1a;Canal Cancal是阿里13年1月开源的一个基于MySql数据库Binlog实现的增量订阅和消费的组件。项目取名Canal取自管道的英文单词&#xff0c;流转的医生&#xff0c;是一个定位于基于MySql数据库Binlog增量日志来实现数据库镜像&…

你遇到的面试官是「伯乐」吗?

之前写了一篇应应聘者视角的「面试中要注意的点」&#xff0c;《聊聊面试的事&#xff08;应聘方&#xff09;》。这次再来一篇面试官视角的。如果你不是面试官&#xff0c;也没关系。所谓“知己知彼&#xff0c;方能百战百胜”&#xff0c;了解一下面试官在面试时的侧重点&…

记录一次线上超时异常查询

线上事故复盘 前言 前一次上线&#xff0c;当时正常&#xff0c;第二天发现有部分超时报警&#xff0c;最终发现应为Dubbo接口一次传输数据量太大导致线程虚拟内存占用 线上问题排查过程 报警邮件中查询到有一部分接口超时量激增&#xff0c;查询定位到某个Dubbo接口&#x…

没用过.gitignore还敢自称高级开发?

Git是跟踪项目中所有文件的好工具&#xff0c; 但是&#xff0c;您会希望在项目的整个生命周期中不要跟踪某些文件及其变更。系统文件&#xff08;i.e. Mac系统的.Ds_Store&#xff09;应用程序配置文件&#xff08;i.e. app.config, .env&#xff09;构建组件&#xff08;i.e.…

支付价格计算中精度问题之double,float

前言 前段时间开发新的微信小程序&#xff0c;借此机会将老掉牙的支付模块重构&#xff0c;并且支持现金支付&#xff08;之前都是虚拟币支付&#xff09;&#xff0c;在重构期间遇到计算上的一些精度问题&#xff0c;虽然数额影响非常小但是影响比较大&#xff0c;我觉得有必…

.net core 集成 sentry 进行异常报警

.net core 集成 sentry 进行异常报警IntroSentry 是一个实时事件日志记录和汇集的平台。其专注于错误监控以及提取一切事后处理所需信息而不依赖于麻烦的用户反馈。它分为客户端和服务端&#xff0c;客户端(目前客户端有 C#, Python, PHP, JavaScript, Ruby等多种语言)就嵌入在…

[Qt入门]QTableWidget控件创建

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget) {ui->setupUi(this);//TableWidget控件//设置列数ui->tableWidget->setColumnCount(3);//设置水平表头ui->tableWidget->…

Zookeeper--Watcher机制源码剖析一

Watcher-- 数据变更通知 我们知道Zookeeper提供来分布式数据的订阅/发布功能&#xff0c;一个典型的发布/订阅模型系统定义了一种一对多的订阅关系&#xff0c;能让多个订阅者同时监听某个主题对象&#xff0c;当这个被监听对象自身状态发生变化时候&#xff0c;会通知所有订阅…

.NET Core 3.1 的REST 和gRPC 性能测试

看到越南小哥 的github 上的Evaluating Performance of REST vs. gRPC &#xff0c; 使用的是.NET Core 3.0 , 今天我把它升级到.NET Core 3.1 同样做了一个测试&#xff0c;文章的结果和他的博客文章是一样的&#xff1a;https://dev.to/thangchung/performance-benchmark-grp…

Zookeeper--Watcher机制源码剖析二

Watcher触发 我们从实际操作时候的表现来看Watcher的触发&#xff0c;比如Zookeeper中NodeDataChanged时间的触发是“Watcher监听的对应数据节点的数据内容发生变更”&#xff0c;需要修改节点数据那么必然和数据节点存储的位置DataTree有关系&#xff0c;我们从这里去寻找修改…