前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ASP.NET-FineUI开发实践-13(一)

ASP.NET-FineUI开发实践-13(一)

作者头像
冰封一夏
发布2019-09-11 15:31:11
6400
发布2019-09-11 15:31:11
举报

开原版好像是没有gird树,有一个扩展列下的模拟树列,就是不能展开,专业版有,开原版我弄了弄,思路是有,就是不是很好实现。这篇博客直接写出了(一)说明一个肯定是写不完的。

FineUI重在封装,改这个我也不打算大量的js实现,最起码前台传几个属性就可以了,后台就都实现了,这是初衷,就是有点慢,太慢的话以后会改成前台实现的。以前我修改的或新建的不管是前后台方法都是可以通用的,尽量避免一个页面写一遍,那不是好代码。

1.核心

对于显示树层级,主要的就是缩进,这个弄好了就可以了,好在列有个DataSimulateTreeLevelField属性,根本就不用担心,这里传的是层级,有就传,没有就创造,先放着。当然不能有也只能重写数据源,这也是树grid慢的原因之一。

考虑完显示就是考虑展开和收起,方法先不谈,方法是被触发的,这里就要靠点击触发展开收起方法,专业版是个箭头,我也找了个图标,每个行放一个,这就用到了重写数据源,有很多地方可以写:绑定之前,绑定之后渲染之前,行绑定事件里,也可以跟踪DataSimulateTreeLevelField属性,他就是加了个图标,他怎么加的我怎么加就可以了。图标的触发就是jq了,其实完全可以写成自定义事件就是给grid加个事件,这个也是后话。

触发完了才是展开和收起的方法,一下就让我想到了删除和添加,不就是删除指定行和添加指定行么,但是添加有难度,删除了数据丢了我加谁,但是通过实验我看见js执行的删除没有真的删除数据源,只是把显示的扔了,这就好办了,重新绑一下又回来了(这个是从Demo里删除后需要保存想到的),那么只有删除,控制了删除和重新载入数据源就可以实现展开了。删除方法 store.removeAt(rowIndex); 重新载入.f_loadData(); 很容易能找到。

2.参数

刚说用参数实现了,看到专业版用到的参数有 是否开启树,树字段的列名,树ID,父ID

说谢谢就可以拿来用了,目前够用了。注意我这里的树ID和父ID不是数据源,而是列名ColumnID

代码语言:javascript
复制
        /// <summary>
        /// 是否启用树
        /// </summary>
        [Category(CategoryName.OPTIONS)]
        [DefaultValue(null)]
        [Description("是否启用树")]
        public bool EnableTree
        {
            get
            {
                object obj = FState["EnableTree"];
                return obj == null ? false : (bool)obj;
            }
            set
            {
                FState["EnableTree"] = value;
                if (value)
                {
                    EnableRowClickEvent = true;
                }
            }
        }
        /// <summary>
        /// 树节点列名
        /// </summary>
        [Category(CategoryName.OPTIONS)]
        [DefaultValue(null)]
        [Description("树节点列名")]
        public string TreeName
        {
            get
            {
                object obj = FState["TreeName"];
                return obj == null ? "" : (string)obj;
            }
            set
            {
                FState["TreeName"] = value;
            }
        }

        /// <summary>
        /// 主键ID
        /// </summary>
        [Category(CategoryName.OPTIONS)]
        [DefaultValue(null)]
        [Description("主键ID")]
        public string TreeDataIDField
        {
            get
            {
                object obj = FState["TreeDataIDField"];
                return obj == null ? "" : (string)obj;
            }
            set
            {
                FState["TreeDataIDField"] = value;
            }
        }
        /// <summary>
        /// 父节点列名
        /// </summary>
        [Category(CategoryName.OPTIONS)]
        [DefaultValue(null)]
        [Description("父节点列名")]
        public string TreeDataParentIDField
        {
            get
            {
                object obj = FState["TreeDataParentIDField"];
                return obj == null ? "" : (string)obj;
            }
            set
            {
                FState["TreeDataParentIDField"] = value;
            }
        }

3.显示方法

首先我找到了用到DataSimulateTreeLevelField属性的方法,方法名称为Grid.AfterDataBind

很明显绑定之后触发的,好吧一切从这里开始。

意思就是如果有这样的列,拿出来,这是我写的

如果开着树,列名不为空,找到列。

再往下,其实现在DataSimulateTreeLevelField是没有值的,写我的

得到层级方法GetLevelNub,通过什么得到呢?数据源,看我传的参数,数据源绑定后变成了Rows,行的集合,操作这个就可以了,根本就不用考虑是DataTable还是IEnumerable

代码语言:javascript
复制
 /// <summary>
        /// 得到当然行的层级
        /// </summary>
        /// <param name="row">当前行</param>
        /// <param name="Rows">行数据集</param>
        /// <returns>层级</returns>
        private int GetLevelNub(GridRow row, GridRowCollection Rows)
        {
            int lub = 0;
            //ID所在列
            int IDindex = FindColumn(TreeDataIDField).ColumnIndex;
            //父ID所在列
            int ParentIDindex = FindColumn(TreeDataParentIDField).ColumnIndex;
            //如果过是第第一级就是0
            if (row.Values[ParentIDindex].ToString() == "" || row.Values[ParentIDindex].ToString() == "0")
            {
                return lub;
            }
            else
            {
                foreach (GridRow gr in Rows)
                {
                    //如果有父级
                    if (gr.Values[IDindex].ToString() == row.Values[ParentIDindex].ToString())
                    {
                        //层级加1
                        lub++;
                        //查看父级的父级
                        int nub = GetLevelNub(gr, Rows);
                        lub += nub == 0 ? 1 : nub;
                    }
                }
            }
            return lub;
        }

这个方法就是个逻辑的问题,循环得到父级就可以了。这里直接用TreeDataIDField就可以了,因为是参数。

这样就可以了,先看一下下。

我新建了页面,新建了数据源,

代码语言:javascript
复制
<f:Grid EnableCollapse="true" Width="800px" Height="400px" runat="server" DataKeyNames="Id,Name"
        ID="Grid1" EnableTree="true" TreeName="name" TreeDataIDField="id" TreeDataParentIDField="topID" ShowBorder="true"
        ShowHeader="true" Title="树表格" >
        <Columns>
            <f:RowNumberField />
            <f:BoundField ColumnID="name" ExpandUnusedSpace="true" DataField="name" HeaderText="名称" >
            </f:BoundField>
            <f:BoundField  ColumnID="id" DataField="id" Width="50px" HeaderText="ID">
            </f:BoundField>
            <f:BoundField  ColumnID="topID" DataField="topID" Width="50px" HeaderText="topID">
            </f:BoundField>
            <f:BoundField DataField="levelcode" Width="100px" HeaderText="层级编号">
            </f:BoundField>
            <f:BoundField ColumnID="levelnub" DataField="levelnub" Width="100px" HeaderText="层级数">
            </f:BoundField>
            <f:BoundField DataField="subitem" Width="100px" HeaderText="是否为子菜单">
            </f:BoundField>
            <f:BoundField DataField="url" Width="100px" HeaderText="地址">
            </f:BoundField>
        </Columns>
    </f:Grid>

OK缩进起效了。但是层级不对,我的下级2和28是下级1 之后的,这是由于数据源没有按层级排序,看来要写个通过父ID给树结构从新排序的方法。

4.重新排序方法

代码语言:javascript
复制
        /// <summary>
        /// 对rows进行重新排序
        /// </summary>
        private void SortTreeRows()
        {
            GridRowCollection newrows = new GridRowCollection();
            //复制到新列表
            foreach (GridRow row in Rows)
            {
                newrows.Add(row);
            }
            //清空
            Rows.Clear();
            int pidindex = FindColumn(TreeDataParentIDField).ColumnIndex;
            int idindex = FindColumn(TreeDataIDField).ColumnIndex;
            //记录根节点
            GridRowCollection onerows = new GridRowCollection();
            //int i = 0;
            foreach (GridRow row in newrows)
            {
                if (row.Values[pidindex].ToString() == "" || row.Values[pidindex].ToString() == "0")
                {
                    //row.RowIndex = i;
                    //i++;
                    //保存跟节点
                    Rows.Add(row);
                    onerows.Add(row);
                }
            }
            int c = onerows.Count;
            //循环根节点插入子节点
            for (int j = 0; j < c; j++)
            {
                GridRow row = onerows[j];
                //注意起始index计算,从新插入的行开始下一次插入
                BuildTree(Rows.Count - c + j, row, newrows);
            }
            for (int i = 0; i < Rows.Count; i++)
            {
                Rows[i].RowIndex = i;
            }
        }
        /// <summary>
        /// 重构行
        /// </summary>
        /// <param name="j">插入的index</param>
        /// <param name="row">当前row</param>
        /// <param name="rows">集合</param>
        private void BuildTree(int j, GridRow row, GridRowCollection rows)
        {
            //得到下层节点index
            string nexindex = GetNextIndex(row, rows);
            if (nexindex != "")
            {
                string[] s = nexindex.Split(',');
                int c = Rows.Count;
                for (int i = 0; i < s.Length; i++)
                {
                    GridRow dr = rows[Convert.ToInt32(s[i])];
                    //重新计算下一次插入的行号
                    int index = j + i + 1 + (Rows.Count - c);
                    if (Rows.Count != c)
                    {
                        index = index - 1;
                    }
                    //dr.RowIndex = index;
                    Rows.Insert(index, dr);
                    //循环子节点
                    BuildTree(index, dr, rows);
                }
            }
        }

        /// <summary>
        /// 得到下级行号
        /// </summary>
        /// <param name="row">本节点</param>
        /// <param name="Rows">集合</param>
        /// <returns>集合以,隔开</returns>
        private string GetNextIndex(GridRow row, GridRowCollection Rows)
        {
            string topindex = "";
            int pridindex = FindColumn(TreeDataParentIDField).ColumnIndex;
            int idindex = FindColumn(TreeDataIDField).ColumnIndex;
            foreach (GridRow gr in Rows)
            {
                //父ID等于本ID添加到集合
                if (gr.Values[pridindex].ToString() != "" && gr.Values[pridindex].ToString() == row.Values[idindex].ToString())
                {
                    topindex += topindex == "" ? gr.RowIndex.ToString() : "," + gr.RowIndex.ToString();
                }
            }
            return topindex;
        }

逻辑着实的复杂,大体思路是这样滴,先把数据集复制,清空数据集,先找到第一层,Add到Rows,通过第一层找到下一层insert到第一层下,然后逐级insert插入新的子集实现排序,这个方法看着挺恶心,我脑袋也就这样了,各位大大可以帮我写写。

在AfterDataBind里加上这个方法就可以了

可以看到层级正确,点击方法明天再说。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-01-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档