zoukankan      html  css  js  c++  java
  • 玩转控件:对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 == 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我一起探讨。

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

  • 相关阅读:
    每天学习一个设计模式(十二):创建型之单例模式
    每天学习一个设计模式(十一):创建型之原型模式
    每天学习一个设计模式(十):创建型之工厂方法模式
    每天学习一个设计模式(九):创建型之建造者模式
    数据库
    操作系统
    计算机网络
    Java 基础知识
    Linux基本操作
    git 基本操作
  • 原文地址:https://www.cnblogs.com/axing/p/12675074.html
Copyright © 2011-2022 走看看