• 如何快速开发树形列表和分页查询整合的WInform程序界面


    我在做Winform界面的时候,一般都是统一化处理,界面顶部放置一些字段条件供查询,下面就是分页查询列表,展示相关的数据。但有时候碰到一些表字段内容分类比较多,有一些特别重要,如果放在一个树形列表来进行快速分类查询,用户体验应该更好。本篇随笔主要介绍如何快速实现树形列表和分页查询整合的WInform程序界面。

    1、标准WInform列表界面

    标准的查询条件+列表数据展示的WInform界面如下所示。

    这个界面主要就是通过代码生成工具(Database2Sharp)进行初期的Winform界面生成即可。要了解具体如何生成标准的列表界面和数据编辑界面,查看下面两篇操作介绍随笔即可。

    利用代码生成工具Database2Sharp设计数据编辑界面》、《代码生成工具之Winform查询列表界面生成》。

    2、树形列表和分页查询整合的Winform程序界面

    以上的界面有时候感觉不够友好,正如文章开头说到,我需要在左边放置一些重要的数据分类进行查询,这样能够提高用户体验效果,最终希望的界面效果如下所示。

    为了实现这种效果,我们需要进行几部操作。

    1)在标准列表界面上增加窗口分割控件(如DevExpress的是SplitContainerControl控件)

     传统的Winform界面可以使用SplitContainer控件

    在现有已生成界面的基础上,把查询部分和列表部分的控件拖动小一点,然后把上述分隔控件拖动到界面后,在右边面板放入已有的查询和分页控件部分的内容,中间状态的列表界面效果如下所示。

    然后在左边放入一个GroupControl控件,并加入树形控件TreeView,这样我们调整后的设计界面效果如下所示。

    首先我们需要在代码里面绑定树的初始化代码,生成需要快速查询的内容,示意代码如下所示。主要逻辑思路就是,从数据字典中检索相关的分类,然后绑定一些查询条件,方便后面的处理。

            private void InitTree()
            {
                base.LoginUserInfo = Cache.Instance["LoginUserInfo"] as LoginUserInfo;
    
                this.treeView1.BeginUpdate();
                this.treeView1.Nodes.Clear();
                //添加一个未分类和全部客户的组别
                TreeNode topNode = new TreeNode("所有记录", 0, 0);
                this.treeView1.Nodes.Add(topNode);
    
                TreeNode CategoryNode = new TreeNode("客户活动类别", 2, 2);
                this.treeView1.Nodes.Add(CategoryNode);
                AddDictData(CategoryNode, 0, "Category");
    
                TreeNode OrderYearNode = new TreeNode("记录年度", 8, 8);
                this.treeView1.Nodes.Add(OrderYearNode);
                List<string> yearList = BLLFactory<Maintenace>.Instance.GetYearList();
                foreach (string year in yearList)
                {
                    TreeNode subNode = new TreeNode(year, 0, 0);
                    subNode.Tag = year;
                    OrderYearNode.Nodes.Add(subNode);
                }
    
    
                this.treeView1.ExpandAll();
                this.treeView1.EndUpdate();
            }

    为了处理树形列表的节点的单击事件,我们可以在其AfterSelect事件进行处理,示意代码如下所示。主要逻辑就是根据及节点和条件的不同,进行不同的处理。

            string treeConditionSql = "";
            private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
            {
                if (e.Node != null && e.Node.Tag != null)
                {
                    if (e.Node.FullPath.Contains("记录年度"))
                    {
                        int year = Convert.ToInt32(e.Node.Tag.ToString());
                        SearchCondition condition = new SearchCondition();
                        condition.AddCondition("StartTime", Convert.ToDateTime(string.Format("{0}-01-01", year)), SqlOperator.MoreThanOrEqual);
                        condition.AddCondition("StartTime", Convert.ToDateTime(string.Format("{0}-01-01", year + 1)), SqlOperator.LessThan);
                        treeConditionSql = condition.BuildConditionSql().Replace("Where", "");
                        BindData();
                    }
                    else
                    {
                        treeConditionSql = e.Node.Tag.ToString();
                        BindData();
                    }
                }
                else
                {
                    treeConditionSql = "";
                    BindData();
                }
            }

    上面的代码,我们定义了一个局部变量treeConditionSql 用来存储树列表单击后的条件,触发单击事件后,我们最终还是传回给标准列表界面已有的查询操作--BindData函数进行处理。

    BindData里面最主要的操作就是构造查询条件,构造条件的语句如下所示,通过SearchCondition对象处理进行使用多数据库的兼容处理。

            /// <summary>
            /// 根据查询条件构造查询语句
            /// </summary> 
            private string GetConditionSql()
            {
                //如果存在高级查询对象信息,则使用高级查询条件,否则使用主表条件查询
                SearchCondition condition = advanceCondition;
                if (condition == null)
                {
                    condition = new SearchCondition();
                    condition.AddCondition("Category", this.txtCategory.Text.Trim(), SqlOperator.Like);
                    condition.AddCondition("Title", this.txtTitle.Text.Trim(), SqlOperator.Like);
                    condition.AddDateCondition("StartTime", this.txtStartTime1, this.txtStartTime2); //日期类型
                    condition.AddCondition("Contact", this.txtContact.Text.Trim(), SqlOperator.Like);
                    condition.AddCondition("Place", this.txtPlace.Text.Trim(), SqlOperator.Like);
                }
                string where = condition.BuildConditionSql().Replace("Where", "");
                //如果是单击节点得到的条件,则使用树列表的,否则使用查询条件的
                if (!string.IsNullOrEmpty(treeConditionSql))
                {
                    where = treeConditionSql;
                } 
    
                return where;
            }

    最终绑定数据的函数BindData的逻辑代码如下所示。

            /// <summary>
            /// 绑定列表数据
            /// </summary>
            private void BindData()
            {
                //entity
                this.winGridViewPager1.DisplayColumns = "Customer_ID,HandNo,Category,Title,Content,StartTime,EndTime,Contact,ContactPhone,ContactMobile,Place,PlaceAddress,PlacePhone,Note,Editor,EditTime";
                this.winGridViewPager1.ColumnNameAlias = BLLFactory<Activity>.Instance.GetColumnNameAlias();//字段列显示名称转义
    
                string where = GetConditionSql();
                List<ActivityInfo> list = BLLFactory<Activity>.Instance.FindWithPager(where, this.winGridViewPager1.PagerInfo);
                this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<ActivityInfo>(list);
                this.winGridViewPager1.PrintTitle = "客户活动管理报表";
            }

    这样我们就完成了树形列表和分页查询整合一起的数据查询处理逻辑,从而实现我们说需要的结果,这样的界面在某种程度上,给我们提供更多的方便,更好的体验。

  • 相关阅读:
    python面试题解析(python基础篇80题)
    python面试题
    网络IO模型 主要 IO多路复用
    线程队列 线程池 协程
    线程的Thread模块 同步控制:锁,事件,信号量,条件,定时器
    进程池,线程的理论,Threading.Thread来创建线程
    进程之间的通信(IPC),对列,管道,数据共享.进程池初识
    Process 进程之间的数据隔离问题,守护进程,锁,信号量,事件
    js get the local domain and path fast
    github jekyll blog
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/3553240.html
Copyright © 2020-2023  润新知