• 使用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或者其他数据库也是一样。

     

    主要研究技术:代码生成工具、会员管理系统、客户关系管理软件、病人资料管理软件、Visio二次开发、酒店管理系统、仓库管理系统等共享软件开发
    专注于Winform开发框架/混合式开发框架Web开发框架Bootstrap开发框架微信门户开发框架的研究及应用
      转载请注明出处:
    撰写人:伍华聪  http://www.iqidi.com 
        
  • 相关阅读:
    关于游戏分布式或者多服管理的想法
    surfaceView
    ackerman递归
    netbeans环境的建立
    copy-浅及深的复制操作
    使用VMware安装CentOS6.8详细教程
    Python在线资源优先级排序
    Python导入模块,Python import用法
    编码
    Python清屏命令
  • 原文地址:https://www.cnblogs.com/wuhuacong/p/1633572.html
Copyright © 2020-2023  润新知