首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET EasyUI ComboTree 下拉樹實作:遞迴載入與父子節點選取邏輯

     編輯:ASP.NET 基礎

前言

企業應用常需呈現多層級部門/分類結構。本文實作基於 EasyUI ComboTree 的下拉樹元件,包含:後端遞迴建構樹形 JSON、前端多選聯動、以及「葉節點全選時自動只保留父節點」的業務邏輯處理。

資料庫設計

CREATE TABLE unit_main (
    unit_id    NUMBER(10) PRIMARY KEY,
    unit_name  VARCHAR2(100) NOT NULL,
    parent_id  NUMBER(10) DEFAULT 0  -- 0 表示根節點
);

資料表結構

實體類別設計

public class Unit {
    public decimal id { get; set; }
    public string text { get; set; }      // EasyUI 顯示文字
    public string state { get; set; }     // "open" 或 "closed"
    public List children { get; set; }

    public Unit() {
        children = new List();
        state = "open";
    }
}

資料存取與遞迴建構

public class UnitComponent {
    private ExeceteOralceSqlHelper SqlHelper = new ExeceteOralceSqlHelper();

    // 取得完整樹結構(根節點)
    public Unit GetUnit() {
        Unit root = new Unit { id = 1000, text = "BO API" };
        root.children = GetUnitList(0);   // 從親代碼 0 開始遞迴
        UnitRecursive(root.children);
        return root;
    }

    // 遞迴處理子節點
    private void UnitRecursive(List units) {
        foreach (var item in units) {
            item.children = GetUnitList(item.id);
            if (item.children != null && item.children.Count > 0) {
                item.state = "closed";    // 有子節點預設收合
                UnitRecursive(item.children);
            }
        }
    }

    // 依 parentID 查詢子部門
    private List GetUnitList(decimal parentID) {
        List list = new List();
        string sql = $"SELECT unit_id, unit_name FROM unit_main WHERE parent_id = {parentID}";
        DataTable dt = SqlHelper.ExecuteDataTable(sql);
        
        if (dt != null && dt.Rows.Count > 0) {
            foreach (DataRow row in dt.Rows) {
                list.Add(new Unit {
                    id = Convert.ToInt32(row["unit_id"]),
                    text = row["unit_name"].ToString()
                });
            }
        }
        return list;
    }
}

一般處理常式輸出 JSON

// Unit.ashx
public void ProcessRequest(HttpContext context) {
    JavaScriptSerializer js = new JavaScriptSerializer();
    context.Response.ContentType = "application/json";
    
    UnitComponent uc = new UnitComponent();
    var root = uc.GetUnit();
    
    // EasyUI ComboTree 期望陣列格式
    context.Response.Write("[" + js.Serialize(root) + "]");
}

ASHX 輸出 JSON 測試

前端頁面整合








ComboTree 介面展示

業務邏輯:葉節點全選時只保留父節點

需求:使用者勾選「應用管理服務中心」及其下所有子節點(xiaobo、tech),提交時只保留父節點 ID。

function computeUnit() {
    // 取得目前勾選的所有節點 ID(含父、子)
    var selected = $("#tbUnit").combotree("getValues").toString().split(",");
    
    // 取得樹物件與所有勾選節點(含未展開的子節點)
    var tree = $('#tbUnit').combotree('tree');
    var checkedNodes = tree.tree('getChecked');
    
    // 遞迴收集所有被勾選父節點的「所有子孫節點 ID」
    var allDescendants = [];
    collectDescendants(tree, checkedNodes, allDescendants);
    
    // 差集運算:選取節點 - 所有子孫節點 = 真正要提交的節點
    var result = arrayDiff(selected, allDescendants);
    alert("最終提交節點:" + result.join(","));
}

// 遞迴收集子孫節點 ID
function collectDescendants(tree, nodes, result) {
    for (var i = 0; i < nodes.length; i++) {
        if (!tree.tree('isLeaf', nodes[i].target)) {
            var children = tree.tree('getChildren', nodes[i].target);
            for (var j = 0; j < children.length; j++) {
                result.push(children[j].id);
            }
            collectDescendants(tree, children, result);
        }
    }
}

// 陣列差集:arr1 - arr2
function arrayDiff(arr1, arr2) {
    var res = [];
    for (var i = 0; i < arr1.length; i++) {
        var found = false;
        for (var j = 0; j < arr2.length; j++) {
            if (arr2[j] == arr1[i]) { found = true; break; }
        }
        if (!found) res.push(arr1[i]);
    }
    return res;
}

關鍵技術點總結

技術點實作方式
樹形資料結構遞迴 C# 類別 + EasyUI 要求的 JSON 格式(id, text, state, children)
資料載入一般處理常式輸出 JSON,ComboTree 自動解析
父子聯動選取cascadeCheck: true
多選模式multiple: true
業務邏輯處理前端 JS 遞迴遍歷樹物件,陣列差集運算過濾冗餘子節點

結語

ComboTree 結合後端遞迴查詢與前端樹操作 API,能優雅解決多層級分類選取需求。關鍵在於理解 EasyUI 的資料格式規範,以及善用 tree('getChecked')、tree('getChildren') 等 API 處理複雜選取邏輯。本文範例可直接套用至部門選擇、權限分配、分類管理等場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved