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

简介:

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

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

本文的经营范围是一个可以输入分类及详细子内容的,由于内容繁多,而且具有一定的层次关系,因此,不适合采用DropdownListCheckboxList控件,因此采用了带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 == nullreturn;
                
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(0string.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来构建用户选择输入,如需转载请自行联系原博主。



 

目录
相关文章
|
3月前
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
154 10
|
7月前
|
消息中间件 前端开发 小程序
一个基于.NET Core构建的简单、跨平台、模块化的商城系统
今天大姚给大家分享一个基于.NET Core构建的简单、跨平台、模块化、完全开源免费(MIT License)的商城系统:Module Shop。
109 2
|
28天前
|
Kubernetes Cloud Native Ubuntu
庆祝 .NET 9 正式版发布与 Dapr 从 CNCF 毕业:构建高效云原生应用的最佳实践
2024年11月13日,.NET 9 正式版发布,Dapr 从 CNCF 毕业,标志着云原生技术的成熟。本文介绍如何使用 .NET 9 Aspire、Dapr 1.14.4、Kubernetes 1.31.0/Containerd 1.7.14、Ubuntu Server 24.04 LTS 和 Podman 5.3.0-rc3 构建高效、可靠的云原生应用。涵盖环境准备、应用开发、Dapr 集成、容器化和 Kubernetes 部署等内容。
46 5
|
4月前
|
设计模式 存储 前端开发
揭秘.NET架构设计模式:如何构建坚不可摧的系统?掌握这些,让你的项目无懈可击!
【8月更文挑战第28天】在软件开发中,设计模式是解决常见问题的经典方案,助力构建可维护、可扩展的系统。本文探讨了.NET中三种关键架构设计模式:MVC、依赖注入与仓储模式,并提供了示例代码。MVC通过模型、视图和控制器分离关注点;依赖注入则通过外部管理组件依赖提升复用性和可测性;仓储模式则统一数据访问接口,分离数据逻辑与业务逻辑。掌握这些模式有助于开发者优化系统架构,提升软件质量。
60 5
|
7月前
|
开发框架 缓存 前端开发
利用Visual Basic构建高效的ASP.NET Web应用
【4月更文挑战第27天】本文探讨使用Visual Basic与ASP.NET创建高效Web应用的策略,包括了解两者基础、项目规划、MVC架构、数据访问与缓存、代码优化、异步编程、安全性、测试及部署维护。通过这些步骤,开发者能构建出快速、可靠且安全的Web应用,适应不断进步的技术环境。
106 0
|
4月前
|
机器学习/深度学习 人工智能 算法
【悬念揭秘】ML.NET:那片未被探索的机器学习宝藏,如何让普通开发者一夜变身AI高手?——从零开始,揭秘构建智能应用的神秘旅程!
【8月更文挑战第28天】ML.NET 是微软推出的一款开源机器学习框架,专为希望在本地应用中嵌入智能功能的 .NET 开发者设计。无需深厚的数据科学背景,即可实现预测分析、推荐系统和图像识别等功能。它支持多种数据源,提供丰富的预处理工具和多样化的机器学习算法,简化了数据处理和模型训练流程。
59 1
|
4月前
|
存储 缓存 安全
.NET 在金融行业的应用:高并发交易系统的构建与优化之路
【8月更文挑战第28天】在金融行业,交易系统需具备高并发处理、低延迟及高稳定性和安全性。利用.NET构建此类系统时,可采用异步编程提升并发能力,优化数据库访问以降低延迟,使用缓存减少数据库访问频率,借助分布式事务确保数据一致性,并加强安全性措施。通过综合优化,满足金融行业的严苛要求。
55 1
|
4月前
|
大数据 开发工具 开发者
从零到英雄:.NET核心技术带你踏上编程之旅,构建首个应用,开启你的数字世界探险!
【8月更文挑战第28天】本文带领读者从零开始,使用强大的.NET平台搭建首个控制台应用。无论你是新手还是希望扩展技能的开发者,都能通过本文逐步掌握.NET的核心技术。从环境搭建到创建项目,再到编写和运行代码,详细步骤助你轻松上手。通过计算两数之和的小项目,你不仅能快速入门,还能为未来开发更复杂的应用奠定基础。希望本文为你的.NET学习之旅开启新篇章!
35 1
|
4月前
|
缓存 运维 前端开发
阿里云云效操作报错合集之如何解决在使用流水线构建net8应用时遇到无法构建的报错
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
5月前
|
Kubernetes Cloud Native Linux
如何使用 Containerfile/Dockerfile 构建 .net 镜像?
构建轻量级的 .NET Core 镜像通常涉及到几个关键步骤,主要是选择正确的基础镜像、使用多阶段构建、优化文件结构以及清理不必要的文件。.NET 8 在云原生方面的支持有了显著的增强,这些改进旨在提高性能、减少资源消耗、简化部署流程以及提升应用程序的可观察性和可维护性。
225 5
如何使用 Containerfile/Dockerfile 构建 .net 镜像?