支持树型的GridView

实现思路: 继承自Gridview,处理gridview的数据源,使其在帮定时,就已经按照树型菜单顺序排列好,那样只需在帮定处理其图片是javascript脚本就可以了

源代码下载:http://files.cnblogs.com/wschacker/TreeListView.rar

效果图:

代码:

Code
using System;
    using System.Data;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Text;
    using System.Web;
    using System.IO;
    using System.Drawing;
    using System.Drawing.Design;
    using System.Reflection;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    [ToolboxData("<{0}:TreeListView runat=server></{0}:TreeListView>"), DefaultProperty("Text")]
    public class TreeListView : GridView, IPostBackDataHandler
    {
        public TreeListView()
        {
            base.AllowPaging = false;
            base.AllowSorting = false;
            base.AutoGenerateColumns = false;

        }

        Tree的属性设置#region Tree的属性设置
        private int _nodeColumnIndex;
        /**//// <summary>
        /// 显示树型的列 Index
        /// </summary>
        public int NodeColumnIndex
        {
            get { return this._nodeColumnIndex; }
            set
            {
                _nodeColumnIndex = value;
            }
        }

        private string _columnKey;
        /**//// <summary>
        /// Key字段
        /// </summary>
        public string ColumnKey
        {
            get { return _columnKey; }
            set
            {
                _columnKey = value;
            }
        }

        private string _parentKey;
        /**//// <summary>
        /// 指向父节点的字段
        /// </summary>
        public string ParentKey
        {
            set
            {
                _parentKey = value;
            }
        }

        private string _sortKey;
        /**//// <summary>
        /// 排序字段
        /// </summary>
        public string SortKey
        {
            set { _sortKey = value; }
        }

        private object _rootNodeFlag;
        /**//// <summary>
        /// 根节点的标记 这里采用 ParentKey为什么字符
        /// </summary>
        public object RootNodeFlag
        {
            set
            {
                _rootNodeFlag = value;
            }
        }

        private static string _treeImageFolder = "/Images/Tree/";
        public static string TreeImageFolder
        {
            get
            {
                return _treeImageFolder;
            }
            set
            {
                _treeImageFolder = value;
            }
        }

        private int _expendDepth = 0;
        /**//// <summary>
        /// 展开的深度
        /// </summary>
        public int ExpendDepth
        {
            get
            {
                return _expendDepth;
            }
            set { _expendDepth = value; }
        }
        #endregion

        public override object DataSource
        {
            get
            {
                return base.DataSource;
            }
            set
            {
                DataTable dtSource = new DataTable();
                if (value is DataSet && ((DataSet)value).Tables.Count > 0)
                {
                    DataSet ds = value as DataSet;
                    dtSource = OrderData(ds.Tables[0]);
                }
                else
                {
                    throw new Exception("DataSource is not DataSet!");
                }
                base.DataSource = dtSource;
            }
        }

        DataTable OrderData(DataTable dtSource)
        {
            DataTable dtResult = dtSource.Clone();
            dtResult.Columns.Add("TreeListView$Row$Depth", typeof(int));
            dtResult.Columns.Add("TreeListView$Row$IsLeaf", typeof(bool));
            dtResult.Columns.Add("TreeListView$Row$IsBottom", typeof(bool));
            dtResult.Columns.Add("TreeListView$Row$ParentRow", typeof(DataRow));
            dtResult.Columns.Add("TreeList$ViewRow$ClientID", typeof(string));
            RecursionOrderData(dtSource, dtResult, _rootNodeFlag, -1, null);
            return dtResult;
        }
        string FormatToRowFilter(object val)
        {
            Type type = val.GetType();
            if (type == typeof(string))
            {
                return string.Format("'{0}'", val.ToString().Replace("'", "''"));
            }
            else if (type == typeof(Guid))
            {
                return string.Format("'{0}'", val);
            }
            else if (type.IsValueType)
            {
                return val.ToString();
            }
            else
            {
                return string.Format("'{0}'", val.ToString().Replace("'", "''"));
            }
        }
        bool RecursionOrderData(DataTable dtSource, DataTable dtResult, object parentID, int depth, DataRow parentDatarow)
        {
            DataView dv = new DataView(dtSource);
            dv.RowFilter = string.Format("{0}={1}", _parentKey, FormatToRowFilter(parentID));
            dv.Sort = _sortKey;
            DataRow dr = null;
            depth++;
            for (int i = 0; i < dv.Count; i++)
            {
                dr = dtResult.NewRow();

                for (int j = 0; j < dv[i].Row.ItemArray.Length; j++)
                {
                    dr[j] = dv[i][j];
                }

                if (i == dv.Count - 1) //isBottom
                {
                    dr["TreeListView$Row$IsBottom"] = true;
                }
                else
                {
                    dr["TreeListView$Row$IsBottom"] = false;
                }
                dr["TreeListView$Row$Depth"] = depth;
                dr["TreeListView$Row$ParentRow"] = parentDatarow;
                if (depth == 0)
                {
                    dr["TreeList$ViewRow$ClientID"] = Guid.NewGuid().ToString();
                }
                else
                {
                    dr["TreeList$ViewRow$ClientID"] = parentDatarow["TreeList$ViewRow$ClientID"].ToString() + "/" + Guid.NewGuid().ToString();
                }

                dtResult.Rows.Add(dr);
                dr["TreeListView$Row$IsLeaf"] = !RecursionOrderData(dtSource, dtResult, dv[i][_columnKey], depth, dr);
            }

            return dv.Count > 0;
        }

        public override bool AllowPaging
        {
            get
            {
                return base.AllowPaging;
            }
            set
            {
                base.AllowPaging = false;
            }
        }

        public override bool AutoGenerateColumns
        {
            get
            {
                return base.AutoGenerateColumns;
            }
            set
            {
                base.AutoGenerateColumns = false;
            }
        }

        重载:CreateRow#region 重载:CreateRow
        protected override GridViewRow CreateRow(int rowIndex, int dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState)
        {
            return new TreeListViewRow(rowIndex, dataSourceIndex, rowType, rowState);
        }
        #endregion

        重写:Rows#region 重写:Rows
        private TreeListViewRowCollection _rowsCollection;
        [Browsable(false)]
        public new TreeListViewRowCollection Rows
        {
            get
            {
                ArrayList _rowsArray = new ArrayList();
                for (int i = 0; i < base.Rows.Count; i++)
                {
                    _rowsArray.Add((TreeListViewRow)base.Rows[i]);
                }
                this._rowsCollection = new TreeListViewRowCollection(_rowsArray);
                return this._rowsCollection;
            }
        }
        #endregion

        重载:OnInit#region 重载:OnInit
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            Page.RegisterRequiresPostBack(this);

            if (!Page.ClientScript.IsClientScriptIncludeRegistered("JS_TreeListView"))
            {
                this.Page.ClientScript.RegisterClientScriptInclude(this.GetType(), "JS_TreeListView", Page.ClientScript.GetWebResourceUrl(this.GetType(), "GoldMantis.Web.UI.Resource.TreeListView.JS_TreeListView.js"));
            }
        }
        #endregion

        IPostBackDataHandler Members#region IPostBackDataHandler Members

        public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
        {
            return false;
        }

        public void RaisePostDataChangedEvent()
        {

        }

        #endregion

        方法:RenderCheckBoxExField#region 方法:RenderCheckBoxExField
        /**//// <summary>
        /// 处理CheckBoxExField类型的列
        /// </summary>
        private void RenderCheckBoxExField()
        {
            if (!this.ShowHeader && !this.ShowFooter)
            {
                return;
            } 

            foreach (DataControlField field in Columns)
            {
                if (field is CheckBoxExField)
                {
                    int checkBoxExFieldIndex = Columns.IndexOf(field) + this.GetAutoGenerateButtonCount();
                    foreach (GridViewRow row in Rows)
                    {
                        if (row.RowType == DataControlRowType.Header)
                        {
                            row.Cells[checkBoxExFieldIndex].Controls.Clear();
                        }
                        if (row.RowType == DataControlRowType.DataRow)
                        {
                            row.Cells[checkBoxExFieldIndex].Controls[0].ID = "cbChoose";
                            ((CheckBox)row.Cells[checkBoxExFieldIndex].Controls[0]).Attributes.Add("onclick", "ChooseTree(this);");
                        }
                    }

                    注册脚本#region 注册脚本
                    string script = @"
    var modifyId = """" ;
    var choosedId = """";
    var choosedIndex; 
    function ChooseTree(obj)
    {
        var cTrId = obj.parentElement.parentElement.parentElement.id;
        var treeTable = document.getElementById("""+this.ClientID+@""");
        for( var i = 0; i < treeTable.rows.length; i++ )
        {
            if( treeTable.rows[i].id.indexOf(cTrId) != -1 && treeTable.rows[i].id != cTrId )
            {
                document.getElementById(treeTable.rows[i].id+""_cbChoose"").checked = obj.checked;
            }
        }
        choosedId = """";
        choosedIndex = new Array();
        for( var i = 1; i < treeTable.rows.length; i++ )
        {
            if( document.getElementById(treeTable.rows[i].id+""_cbChoose"").checked )
            {
                choosedId += treeTable.rows[i].id.substring(treeTable.rows[i].id.lastIndexOf(""/"")+1) + "","";
                choosedIndex.push(i);
            }
        }
        
        choosedId = choosedId.substring(0,choosedId.length-1); 
    }";
                    if (!Page.ClientScript.IsStartupScriptRegistered("TreeListView_CheckBoxExField"))
                    {
                        Page.ClientScript.RegisterStartupScript(GetType(), "TreeListView_CheckBoxExField", script, true);
                    }
                    #endregion
                }
            }
        }
        方法:GetAutoGenerateButtonCount#region 方法:GetAutoGenerateButtonCount
        private int GetAutoGenerateButtonCount()
        {
            int num = 0;
            if (this.AutoGenerateDeleteButton || this.AutoGenerateEditButton || this.AutoGenerateSelectButton)
            {
                num = 1;
            }
            return num;
        }
        #endregion
        #endregion

        protected override void Render(HtmlTextWriter writer)
        {
            RenderCheckBoxExField();
            base.Render(writer);
        }
    }
 public class TreeListViewRow : GridViewRow
    {
        public TreeListViewRow(int rowIndex, int dataItemIndex, DataControlRowType rowType, DataControlRowState rowState)
            : base(rowIndex, dataItemIndex, rowType, rowState)
        {

        }
        
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (this.RowType == DataControlRowType.DataRow)
            {
                if (this.Parent.Parent is TreeListView)
                {
                    TreeListView treeListView = this.Parent.Parent as TreeListView;
                    DataRow dr = ((DataTable)treeListView.DataSource).Rows[this.DataItemIndex] as DataRow;
                    string str = GetTreeNodeImg(dr, Convert.ToBoolean(dr["TreeListView$Row$IsLeaf"]), Convert.ToBoolean(dr["TreeListView$Row$IsBottom"]));
                    this.Cells[treeListView.NodeColumnIndex].Text = str + this.Cells[treeListView.NodeColumnIndex].Text;
                    this.ID = dr["TreeList$ViewRow$ClientID"].ToString();
                    if (treeListView.ExpendDepth > 0)
                    {
                        this.Style["display"] = treeListView.ExpendDepth >= Convert.ToInt32(dr["TreeListView$Row$Depth"]) ? "block" : "none";
                    }
                }
            }
            
        }

        获取Tree的图片#region 获取Tree的图片
        string GetTreeNodeImg(DataRow dr, bool isLeaf, bool isBottom)
        {
            return GetTreeNodeOtherImg(dr) + GetTreeNodeLastImg(isLeaf, isBottom);
        }
        string GetTreeNodeOtherImg(DataRow dr)
        {
            if (dr["TreeListView$Row$ParentRow"] != null&&!dr["TreeListView$Row$ParentRow"].Equals(DBNull.Value))
            {
                DataRow drParentRow = dr["TreeListView$Row$ParentRow"] as DataRow;
                bool parentIsBottom = Convert.ToBoolean(drParentRow["TreeListView$Row$IsBottom"]);
                if (parentIsBottom)
                {
                    return GetTreeNodeOtherImg(drParentRow) + string.Format("<img src={0} align=absmiddle>", TreeListView.TreeImageFolder + "white.gif");
                }
                else
                {
                    return GetTreeNodeOtherImg(drParentRow) + string.Format("<img src={0} align=absmiddle>", TreeListView.TreeImageFolder + "i.gif");
                }

            }
            else
            {
                return string.Empty;
            }
        }
        string GetTreeNodeLastImg(bool isLeaf, bool isBottom)
        {
            //最后靠近的那个Image
            string lastImg = string.Empty;
            if (isLeaf)
            {
                if (isBottom)
                {
                    lastImg = string.Format("<img src={0} align=absmiddle>", TreeListView.TreeImageFolder + "l.gif");
                }
                else
                {
                    lastImg = string.Format("<img src={0} align=absmiddle>",TreeListView.TreeImageFolder + "t.gif");
                }
            }
            else
            {
                if (isBottom)
                {
                    lastImg = string.Format("<img src={0} align=absmiddle οnclick='ClickNode(this,true,\"{1}\");' style=\"cursor: hand\">", TreeListView.TreeImageFolder + "lminus.gif", this.Parent.Parent.ClientID);
                }
                else
                {
                    lastImg = string.Format("<img src={0} align=absmiddle οnclick='ClickNode(this,true,\"{1}\");' style=\"cursor: hand\">", TreeListView.TreeImageFolder + "tminus.gif", this.Parent.Parent.ClientID);
                }
            }
            return lastImg;

        }
        #endregion

Js代码实现折叠效果

Code

var lExpend = "lminus.gif";
var lPinch = "lplus.gif";   
var tExpend = "tminus.gif";
var tPinch = "tplus.gif";         

function ClickNode(img,isBottom,tableId)
{
    var imgId = img.src.substring(img.src.lastIndexOf("/")+1);
    var url = img.src.substring(0,img.src.lastIndexOf("/")+1);
    var oldTrId = img.parentElement.parentElement.id;
    var newTrId = oldTrId.substring(oldTrId.indexOf("_")+1);
    
    if( isBottom)
    {
        if( imgId == lExpend)
        {
            img.src =  url+ lPinch;
            img.parentElement.id = lPinch;
            PinchNode(newTrId,oldTrId,tableId);
        }
        else
        {
            img.src = url + lExpend;
            img.parentElement.id = lExpend;
            ExpendNode(newTrId,oldTrId,tableId);
        }   
    }
    else
    {
        if( imgId == tExpend )
        {
            img.src =  url+ tPinch;
            img.parentElement.id = tPinch;
            PinchNode(newTrId,oldTrId,tableId);
      
        }
        else
        {
            img.src = url + tExpend;
            img.parentElement.id = tExpend;
            ExpendNode(newTrId,oldTrId,tableId);
        }   
    }
}

function ExpendNode(newId,oldId,tableId)
{
    var tree = document.getElementById(tableId);
    for( var i = 0; i < tree.rows.length; i++ )
    {
        if( tree.rows[i].id.indexOf(newId) != -1 && tree.rows[i].id != oldId )
        {
            var isExpend = true;
            var pId = tree.rows[i].id;
           
            while( pId != oldId)
            {
                for( var j = 0; j < 2; j++ )
                    pId = pId.substring( 0,pId.lastIndexOf("/"));
                var parent = document.getElementById(pId);
                if( parent != null )
                {
                    var tempId = parent.cells[2].id;
                    if( tempId == lExpend || tempId == tExpend || tempId == "")
                        ;
                    else
                    {
                        isExpend = false;
                        break;
                    }
                }
                else
                    break;
            }
            if( isExpend )
               tree.rows[i].style.display="block";  
        }
    }
}

function PinchNode(newId,oldId,tableId)
{
    var tree = document.getElementById(tableId);
    for( var i = 0; i < tree.rows.length; i++ )
    {
        if( tree.rows[i].id.indexOf(newId) != -1 && tree.rows[i].id != oldId)
        {
            tree.rows[i].style.display = "none";
        }
    }
}

转载于:https://www.cnblogs.com/wschacker/archive/2008/07/24/1250446.html

支持树型的GridView控件相关推荐

  1. Delphi 7下使用VT实现树型列表结合控件

    Delphi 7下使用VT实现树型列表结合控件 转载于:https://www.cnblogs.com/LittleTiger/p/5007580.html

  2. GridView控件详解

    GridView是ASP.NET 1.x的DataGrid控件的后继者.它提供了相同的基本功能集,同时增加了大量扩展和改进.如前所述,DataGrid(ASP.NET 2.0仍然完全支持)是一个功能非 ...

  3. 扩展GridView控件——为内容项添加拖放及分组功能

    引言 相信大家对GridView都不陌生,是非常有用的控件,用于平铺有序的显示多个内容项.打开任何WinRT应用或者是微软合作商的网站,都会在APP中发现GridView的使用."Tiles ...

  4. 自学Web开发第十四天-基于VB和ASP.NET;丰富数据呈现:TreeView控件的使用及与GridView控件联动,深入研究从GridView中取数据

    自学Web开发第十四天-基于VB和ASP.NET:丰富数据呈现:TreeView控件的使用及与GridView控件联动,深入研究从GridView中取数据 GridView操作数据库后,刷新TreeV ...

  5. 在 GridView 控件中添加一列复选框51

    简介 在前面的教程中 , 我们学习了如何为 GridView 控件添加一列 单选 按钮来选择一个特定的记录.当用户被限制最多只能从网格中选中一项时,一列单选按钮是一个非常恰当的用户界面.然而,有时我们 ...

  6. 使用ASP.NET 2.0中的GridView控件

    在ASP.NET 2.0中,加入了许多新的功能和控件,相比asp.net 1.0/1.1,在各方面都有了很大的提高.其中,在数据控件方面,增加了不少控件,其中的gridview控件功能十分强大.在本文 ...

  7. 扩展GridView控件(2) - 复合排序和排序状态提示

    GridView既强大又好用.为了让它更强大.更好用,我们来写一个继承自GridView的控件. [索引页] [源码下载] 扩展GridView控件(2) - 复合排序和排序状态提示 作者:webab ...

  8. C#中GridView控件的使用

    C#中GridView控件的使用 一.GridView和DataGrid的异同 GridView 是 DataGrid的后继控件,在 framework 2中,虽然还存在DataGrid,但是Grid ...

  9. 【ASP.NET】第八课——GridView 控件的编辑功能优化,GridView控件中嵌套DropDownList控件

    知识点:掌握 GridView 的编辑.高亮显示的功能 .GridView控件中嵌套DropDownList控件获取数据源. [ASP.NET]第七课--数据绑定和 GridView 控件的使用 重点 ...

  10. [GridView控件]事件详解

    GridView是一个非常强大的控件,它支持分页,排序等等,我想每个人都应该用过这个控件,最近有个网友问了我一些问题,平时也没多大的注意,只要能满足自己的一些需求就没有深入的研究.通过了一段时间的研究 ...

最新文章

  1. 调用个别f5 负载端口为80的vs时,返回值为空的问题
  2. windows 导出 oracle,windows 环境下oracle导入导出
  3. 微信小程序连接阿里云物联网
  4. SocketLog-微信调试、API调试和AJAX的调试的工具,能将日志通过WebSocket输出到Chrome浏览器的console中
  5. netstat命令使用范例
  6. C#中的继承与多态还有接口
  7. (2021年)IT技术分享社区个人文章汇总(电脑技巧篇)
  8. 95-10-092-启动-TokenManager
  9. python函数的使用方法_Python函数使用
  10. Mysql学习总结(68)——MYSQL统计每天、每周、每月、每年数据 SQL 总结
  11. oracle字符串处理substr、dbms_lob.substr、case when
  12. Togu Audio Line推出最新版本的TAL-BassLine-101插件 支持M1芯片
  13. 阶段3 2.Spring_02.程序间耦合_1 编写jdbc的工程代码用于分析程序的耦合
  14. 【翻译】Adaptive Convolutions for Structure-Aware Style Transfer
  15. stokes方程matlab,【Fluent】雷诺方程:推导与求解(附MATLAB代码)
  16. CentOS 7.5 安装MySQL教程
  17. html中斜体样式怎么写,html i 斜体标签
  18. 如何给 SAP Commerce Cloud Site 设置默认语言
  19. linux 内存 参数,linux free命令参数及用法详解(linux查看内存命令)
  20. 《易语言百集教程》百集高清教程免费下载地址————【Badboy】

热门文章

  1. c#json对象转数组_C#中将json字符串转为List数组对象
  2. bigdecimal js 判断等于0_Js BigDecimal实现精确加减乘除运算的方法
  3. webview是什么东西_做性能优化前需要考虑什么?
  4. SpringMCV结构
  5. 推荐系统 | 信息过载的大数据时代,大数据推荐系统如何搭建,趋势何方
  6. Vue实现简单Tab标签页组件
  7. 网络是怎样连接的笔记第5章 防火墙,缓存服务器
  8. Libcurl的编译_HTTP/HTTPSclient源代码演示样例
  9. My97 DatePicker 选择时间后弹出选择的时间
  10. geotrellis使用(七)记录一次惨痛的bug调试经历以及求DEM坡度实践