使用Asp.net的TreeView来构建用户选择输入

选择优于输入,这是一般人的共识,面对繁多的数据,提供良好的选择界面,一方面增强用户的界面体验,一方面也提高了数据的准确性,更节省了用户的宝贵时间。一般的单项数据选择可以使用DropdownList控件来实现,但对于有多个选择性输入,而且输入有层次关系的内容,最好选择TreeView控件来实现。

本文介绍如何使用使用TreeView控件来有效获取用户的输入,其中涉及到TreeView控件的级联选择、去掉节点HTML链接变为展开目录、获取选择内容、如何构造数据库的信息变为树形内容以及弹出窗口使用等知识点,本文输入应用级别的例子,希望能做个记号,对己对人,皆为利好!^_^

本文的经营范围是一个可以输入分类及详细子内容的,由于内容繁多,而且具有一定的层次关系,因此,不适合采用DropdownList和CheckboxList控件,因此采用了带CheckBox属性的TreeView控件来辅助用户的输入。

输入界面大致如下所示,用户通过选择按钮,触发弹出对话框,在对话框中放置了TreeView控件。

 

在弹出的对话框中,放置的TreeView控件,一个带有CheckBox,可以方便用户选择,并且具有级联(通过Javascript实现,减少Post回发),另外由于内容比较多,我设置了展开的级别层次。

用户通过选择或者反选大类,可以选择或反选其列表下面的所有项目,也可以单独选择子项目。

 

由于通过Javascript不太好获取并组装返回的内容,本文通过了在后台遍历树的方式对返回值进行处理,然后在父窗体的Javascript中对返回值进行了绑定,使其在界面控件中得以显示指定格式的内容。

 

以下为HTML的代码,其中OnTreeNodeChecked为级联Javascript函数,SubmitValue为对返回值进行绑定的操作。

    <div class="search">
        <span>
            <asp:ImageButton ID="btnSelect" runat="server" 
            ImageUrl="~/Themes/Default/btn_select.gif" onclick="btnSelect_Click"
                />
            <asp:ImageButton ID="btnClose" runat="server" OnClientClick="javascript:window.close();return false;"
                ImageUrl="~/Themes/Default/btn_close.gif" />
        </span>
        <table cellspacing="0" cellpadding="0" border="0" width="100%">
            <tr>
                <td class="ico">
                    &nbsp;
                </td>
                <td class="form">
                    <asp:TreeView ID="TreeView1" runat="server" onclick="OnTreeNodeChecked();" ShowCheckBoxes="All"
                        ShowLines="True" ExpandDepth="1" Font-Bold="False" ForeColor="#0000CC">
                    </asp:TreeView>
                </td>
            </tr>
        </table>
    </div>

    <script language='javascript' type='text/javascript'>
        function OnTreeNodeChecked() {
            var ele = event.srcElement;
            if (ele.type == 'checkbox') {
                var childrenDivID = ele.id.replace('CheckBox', 'Nodes');
                var div = document.getElementById(childrenDivID);
                if (div == null) return;
                var checkBoxs = div.getElementsByTagName('INPUT');
                for (var i = 0; i < checkBoxs.length; i++) {
                    if (checkBoxs[i].type == 'checkbox')
                        checkBoxs[i].checked = ele.checked;
                }
            }
        }

        function SubmitValue() {
            var val = "";
            var returnVal = new Array();
            var inputs = document.all.tags("INPUT");
            var n = 0;
            for (var i = 0; i < inputs.length; i++) // 遍历页面上所有的 input 
            {
                if (inputs[i].type == "checkbox") {
                    if (inputs[i].checked) {
                        var strValue = inputs[i].value;
                        val += strValue + ',';
                        //returnVal[n] = val;
                        n = n + 1;
                    }
                } //if(inputs[i].type="checkbox")
            } //for
            
            window.returnValue = val;
            window.close();
        }
        
    </script>

 下面代码是页面的后台代码,其中展示了如何对树进行数据绑定,使其能够显示有层次格式的内容,其中AddTreeNode是一个递归函数。btnSelect_Click事件处理函数,专门对返回的数据进行组装,以一定的格式显示到客户端的控件输入上。

  代码

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                BindData();
            }
        }

        private void BindData()
        {
            ArrayList scopeTree = BLLFactory<BusinessScope>.Instance.GetTree();
            foreach (BusinessScopeNodeInfo nodeInfo in scopeTree)
            {
                TreeNode node = new TreeNode(nodeInfo.Name);
                node.SelectAction = TreeNodeSelectAction.Expand;
                this.TreeView1.Nodes.Add(node);

                AddTreeNode(node, nodeInfo);
            }
        }

        private void AddTreeNode(TreeNode parentNode, BusinessScopeNodeInfo nodeInfo)
        {
            TreeNode treeNode = null;
            foreach (BusinessScopeNodeInfo subNodeInfo in nodeInfo.Children)
            {
                treeNode = new TreeNode(subNodeInfo.Name);
                treeNode.SelectAction = TreeNodeSelectAction.Expand;
                parentNode.ChildNodes.Add(treeNode);

                AddTreeNode(treeNode, subNodeInfo);
            }
        }

        protected void btnSelect_Click(object sender, ImageClickEventArgs e)
        {
            string result = "";
            foreach (TreeNode parent in this.TreeView1.Nodes)
            {
                foreach (TreeNode node in parent.ChildNodes)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (TreeNode subNode in node.ChildNodes)
                    {
                        if (subNode.Checked)
                        {
                            sb.AppendFormat("{0},", subNode.Text);
                        }
                    }
                    if (sb.Length > 0)
                    {
                        sb.Insert(0, string.Format("{0}(", node.Text));
                        sb.Append(")");
                        result += sb.ToString().Replace(",)", ")") + ";";
                    }
                    else if (node.Checked)
                    {
                        result += node.Text;
                    }                    
                }
            }
            Helper.CloseWin(this, result.Trim(';'));
        }

 

 其中数的数据组装也是需要注意的一个地方,为了提高效率,避免频繁查找数据库,我们先把符合条件的数据放到DataTable,然后通过对象的Select在内存中查找,这样可以很好的提高递归函数的查找效率。

  代码

        /// <summary>
        /// 获取数据树
        /// </summary>
        /// <returns></returns>
        public ArrayList GetTree()
        {
            ArrayList arrReturn = new ArrayList();
            string sql = string.Format("Select * From {0} Order By PID, Seq ", tableName);
            Database db = DatabaseFactory.CreateDatabase();
            DbCommand cmdWrapper = db.GetSqlStringCommand(sql);

            DataSet ds = db.ExecuteDataSet(cmdWrapper);
            if (ds.Tables.Count > 0)
            {
                DataTable dt = ds.Tables[0];
                DataRow[] dataRows = dt.Select(string.Format(" PID = {0}", -1));
                for (int i = 0; i < dataRows.Length; i++)
                {
                    int id = Convert.ToInt32(dataRows[i]["ID"]);
                    BusinessScopeNodeInfo menuNodeInfo = GetNode(id, dt);
                    arrReturn.Add(menuNodeInfo);
                }
            }

            return arrReturn;
        }

        private BusinessScopeNodeInfo GetNode(int id, DataTable dt)
        {
            BusinessScopeInfo menuInfo = this.FindByID(id);
            BusinessScopeNodeInfo menuNodeInfo = new BusinessScopeNodeInfo(menuInfo);

            DataRow[] dChildRows = dt.Select(string.Format(" PID={0}", id));

            for (int i = 0; i < dChildRows.Length; i++)
            {
                int childId = Convert.ToInt32(dChildRows[i]["ID"]);
                BusinessScopeNodeInfo childNodeInfo = GetNode(childId, dt);
                menuNodeInfo.Children.Add(childNodeInfo);
            }
            return menuNodeInfo;
        }

 其中所用到的数据实体如下面两个类所示,其中BusinessScopeNodeInfo 是对象 BusinessScopeInfo的进一步封装,方便提供树的基本信息,也就是BusinessScopeNodeInfo 是一个包含了子类数据的对象,BusinessScopeInfo仅仅是数据库对象的映射实体。

代码

    /// <summary>
    /// BusinessScopeNodeInfo 的摘要说明。
    /// </summary>
    public class BusinessScopeNodeInfo : BusinessScopeInfo
    {
        private ArrayList m_Children = new ArrayList();

        /// <summary>
        /// 子菜单实体类对象集合
        /// </summary>
        public ArrayList Children
        {
            get { return m_Children; }
            set { m_Children = value; }
        }

        public BusinessScopeNodeInfo()
        {
            this.m_Children = new ArrayList();
        }

        public BusinessScopeNodeInfo(BusinessScopeInfo scopeInfo)
        {
            base.Id = scopeInfo.Id;
            base.Name = scopeInfo.Name;
            base.Seq = scopeInfo.Seq;
        }
    }

    [Serializable]
    public class BusinessScopeInfo : BaseEntity
    {    
        #region Field Members

        private decimal m_Id = 0;         
        private decimal m_Pid = -1;         
        private string m_Name = "";         
        private string m_Seq = "";         

        #endregion

        #region Property Members
        
        public virtual decimal Id
        {
            get
            {
                return this.m_Id;
            }
            set
            {
                this.m_Id = value;
            }
        }

        public virtual decimal Pid
        {
            get
            {
                return this.m_Pid;
            }
            set
            {
                this.m_Pid = value;
            }
        }

        public virtual string Name
        {
            get
            {
                return this.m_Name;
            }
            set
            {
                this.m_Name = value;
            }
        }

        public virtual string Seq
        {
            get
            {
                return this.m_Seq;
            }
            set
            {
                this.m_Seq = value;
            }
        }

        #endregion

    }

其中的数据格式大致如下(本文的例子是在Oracle环境中工作的),其实SqlServer或者其他数据库也是一样。

本文转自博客园伍华聪的博客,原文链接:使用Asp.net的TreeView来构建用户选择输入,如需转载请自行联系原博主。

 

时间: 2024-07-30 10:32:45

使用Asp.net的TreeView来构建用户选择输入的相关文章

Asp.net TreeView来构建用户选择输入的方法 推荐_实用技巧

一般的单项数据选择可以使用DropdownList控件来实现,但对于有多个选择性输入,而且输入有层次关系的内容,最好选择TreeView控件来实现. 本文介绍如何使用使用TreeView控件来有效获取用户的输入,其中涉及到TreeView控件的级联选择.去掉节点HTML链接变为展开目录.获取选择内容.如何构造数据库的信息变为树形内容以及弹出窗口使用等知识点,本文输入应用级别的例子,希望能做个记号,对己对人,皆为利好!^_^ 本文的经营范围是一个可以输入分类及详细子内容的,由于内容繁多,而且具有一

使用DataGridView数据窗口控件,构建用户快速输入体验

在"随风飘散" 博客里面,介绍了一个不错的DataGridView数据窗口控件<DataGridView数据窗口控件开发方法及其源码提供下载>,这种控件在有些场合下,还是非常直观的.因为,在一般要求客户录入数据的地方,一般有两种途径,其一是通过弹出一个新的窗口,在里面列出各种需要输入的要素,然后保存的,如下图所示:   其二就是直接在DataGridView中直接输入.这两种方式各有优劣,本文介绍采用该控件实现第二种模式的数据数据.如下图所示    这种方式,直接通过在Da

ASP.NET:DataList控件的选择输入功能

asp.net|控件     利用DataList控件的<SelectedItemTemplate> 属性,就可以随心所欲的布置表中的数据.根据链接,友好地显示出用户感兴趣的数据,我们来看下面的实例.     9.3.2 DataList控件的选择输入功能     在DataCon Web 项目里添加一个Web 窗体,命名为DataList_Sample2.aspx,添加一个DataList控件,DataList_Sample2.aspx的主要HTML代码如下: <form id=&qu

ASP.NET2.0+SQL Server2005构建多层应用

asp.net|server 随着.NET 2.0的发布,将会使得使用ASP.NET 2.0来构建的Web应用越来越容易.使用ASP.NET 2.0和SQL Server 2005,将会比ASP.NET 1.1更方便地构建多层体系架构的web应用.本文,将使用ASP.NET 2.0和SQL Server 2005 (.net使用Visual Studio 2005 beta 2,SQL Server 2005使用april ctp版本)来构建一个简单的多层应用的例子,并且说明其中在.NET 2.

ASP.NET2.0+SQL Server2005构建多层应用第1/4页_基础应用

[推荐]ASP.NET2.0+SQL Server2005构建多层应用!!!!!@申请加分!@@! [sell=5]随着.NET 2.0的发布,将会使得使用ASP.NET 2.0来构建的Web应用越来越容易.使用ASP.NET 2.0和SQL Server 2005,将会比ASP.NET 1.1更方便地构建多层体系架构的web应用.本文,将使用ASP.NET 2.0和SQL Server 2005 (.net使用Visual Studio 2005 beta 2,SQL Server 2005使

ASP和SQL Server如何构建网页防火墙_MsSql

ASP是Web上的客户机/服务器结构的中间层,虽然它使用脚本语言(Java Script,VB Script等)编写,程序代码在服务器上运行,在客户端仅可看到由ASP输出的动态HTML文件,但ASP仍具有某些漏洞,采取一定手段也可以看到ASP程序的源码.这时,通过ASP与SQL Server相结合,我们可以设计出简单.高效.可靠的应用程序. 为网页设置防火墙的主要目的是根据网页内容对不同来访者提供不同的服务,利用Java Script或VB Script,我们很容易做到这一点.但网页的源码在客户

ASP如何更好的解决用户验证问题

解决|问题 在ASP编程中,身份认证可以说是常要用到的.但怎么样才能做到认证的安全呢?举例:表单提交页面:sub.htm<html><head><title>管理员登陆</title><body><form name="form1" method="post" action="sub.asp"><p> 管理员:<input type="text&q

解决ASP.NET创建的线程的用户改变引发的拒绝访问错误

asp.net|创建|错误|访问|解决 解决ASP.NET创建的线程的用户改变引发的"拒绝访问"错误                ASP.NET创建的线程的用户由<identity impersonate="true"/> 改为NT AUTHORITY\NETWORK SERVICE, 引起"System.UnauthorizedAccessException","拒绝访问"     Dim thr As Thr

ASP.NET中TreeView控件使用小结

asp.net|treeview|控件 中国IT动力,最新最全的IT技术教程最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 未整理篇 | 技术讨论 ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql 服务器 Win2000