缘由

  一切实现来源于需求,目的在于不盲目造轮子,有小伙伴儿在看了《玩转控件:对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 == colName
select 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重新加载了。

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

(原图效果)

(Telephone列上移下移确定后效果)

(Email列置顶效果)

(隐藏列效果)

(列宽设置效果)

(motto左冻结效果)

(右冻结效果)

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

结束语

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

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

玩转控件:对Dev的GridControl控件扩展的更多相关文章

  1. 玩转控件:对Dev中GridControl控件的封装和扩展

    又是一年清明节至,细雨绵绵犹如泪光,树叶随风摆动.... 转眼间,一年又过去了三分之一,疫情的严峻让不少企业就跟清明时节的树叶一样,摇摇欲坠.裁员的裁员,降薪的降薪,996的996~~说起来都是泪,以 ...

  2. Dev的GridControl控件选择框的使用

    先介绍环境:VS2010,dev11.2 想要达到的效果:,当单击某一行时前面的选择框选中. 在网上找了不少,但是感觉跟我想的做法很不一样(有很多都是再另外添加一个什么CheckBox,这个我在Dev ...

  3. C# WinfForm 控件之dev表格 GridControl

    基本用法 1.新建一个winformAPP 放一个gridControl 为gridC 再放一个button 用法与dataGrid一样 代码如下: /// <summary> /// 显 ...

  4. DEV的GridControl控件的选中列属性设置高光

    设置Run Designer=>Views=> OptionsSelection下面的: EnableAppearanceFocusedCell = False,//鼠标移开,失去焦点,仍 ...

  5. DevExpress控件的GridControl控件小结

    DevExpress控件的GridControl控件小结 (由于开始使用DevExpress控件了,所以要点滴的记录一下) 1.DevExpress控件组中的GridControl控件不能使横向滚动条 ...

  6. 玩转控件:封装Dev的SearchLookupEdit

    鸣谢 随着前面几个章节对控件封装与扩展的分享,不少小伙伴儿们在作者公众号上反馈,并联系作者,表示通过这些系列和源码能学到不少细节上的东西,并运用到了自己的实际项目当中,也有不少伙伴儿反馈更好更优的处理 ...

  7. DEV GridControl控件使用(CheckBox全选、操作按钮、事件处理,获取值)

    1.GridControl控件使用 (1)绑定数据源 //绑定DataTable gridControl1.DataSource = DbHelper.ExecuteDataTable("S ...

  8. GridControl控件的数据显示的样式控制(转)

    如上两图所示,Dev列表控件GridControl默认的格式并没有渐变变色效果,显示的日期数据,也是“yyyy-MM-dd”的格式,而非“yyyy-MM-dd HH:mm:ss”即使对于后面有长格式的 ...

  9. 设置DevExpress GridControl控件时间列显示时、分、秒样式

    如题,如果Dev GridControl控件绑定DataTable数据源时,DataTable中的某一列为Date类型时,GridControl默认显示样式只显示当前日期,并不会将时.分.秒显示出来. ...

随机推荐

  1. MySQL敏感数据加密及解密

    大数据时代的到来,数据成为企业最重要的资产之一,数据加密的也是保护数据资产的重要手段.本文主要在结合学习通过MySQL函数及Python加密方法来演示数据加密的一些简单方式. 1. 准备工作 为了便于 ...

  2. 分享一次C#调用Delphi编写Dll程序

    1.前言: 最近接手了一个项目需要和Delphi语言编写的一个系统进行一些接口的对接,数据在传输过程中采用Des加密方式,因为Delphi 平台的加密方式和C#平台的加密方式不互通,所以采用的方式是C ...

  3. jmeter 性能测试基本过程及示例

    jmeter 为性能测试提供了一下特色: jmeter 可以对测试静态资源(例如 js.html 等)以及动态资源(例如 php.jsp.ajax 等等)进行性能测试jmeter 可以挖掘出系统最大能 ...

  4. MQTT抓包分析

    1. 概述 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,该 ...

  5. python pip 更新失败问题

    通过PIP 安装第三方库的时候出现 pip程序版本过旧,用’python -m pip install --upgrade pip‘安装’提示仍然如下 可以用管理员身份运行windows shell  ...

  6. 【Weiss】【第04章】AVL树例程

    普通的二叉搜索树可能会由于数据不平均.删除产生高度差等原因,使树倾向于不平衡生长,导致操作慢于O(NlogN). 为应对此现象,将搜索.删除.插入的最坏时间也控制在O(NlogN)上,产生了平衡二叉树 ...

  7. annaconda的安装及使用

    一.安装 1.安装包下载: 方式1:官网:https://www.anaconda.com/distribution/ 方式2:清华镜像源:https://mirrors.tuna.tsinghua. ...

  8. 【JAVA进阶架构师指南】之三:深入了解类加载机制

    前言   在上一篇文章中,我们知道了JVM的内存划分,其中在说到方法区的时候说到方法区中存放的信息包括[已被JVM加载的类信息,常量,静态变量,即时编译的代码等],整个方法区其实就和类加载有关. 类加 ...

  9. ngzorro draw 第一次打开 ERROR TypeError: Cannot read property 'overlayElement' of undefined

    at NzDrawerComponent.push../node_modules/ng-zorro-antd/fesm5/ng-zorro-antd.js.NzDrawerComponent.trap ...

  10. ijkplayer中遇到的问题汇总

    在做音频播放的时候,很多公司使用的是开源的ijkplayer播放器,ijkplayer底层是基于ffmpeg,在某机型上面可能常常遇到各种问题.今天整理了大家在使用ijkplayer中遇到的问题,以及 ...