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

Winform權限框架:TreeListLookupEdit實現級聯下拉樹選擇完整指南

     編輯:關於.NET

在用戶編輯界面中,「所屬公司 → 所屬部門 → 直屬經理」三級級聯選擇是高頻需求。本文深度解析Winform開發框架如何利用DevExpress TreeListLookupEdit 控件,封裝可復用用戶控件,實現下拉面板內直接呈現樹形層級、支持圖標區分節點類型、且具備完整級聯聯動與數據綁定能力的優雅方案。

一、 界面效果與交互邏輯

系統用戶管理主界面

用戶編輯界面三級級聯

交互流程:

  1. 點擊「所屬公司」下拉,樹形列表展示「集團 → 分公司」兩級結構,節點前圖標區分類型。
  2. 選定公司後,「所屬部門」下拉自動過濾該公司下的部門樹,同樣支持多級遞歸。
  3. 選定部門後,「直屬經理」下拉加載該部門人員列表(普通下拉即可)。

所屬公司下拉樹

所屬部門下拉樹

二、 用戶控件封裝設計

將「所屬公司」「所屬部門」分別封裝為繼承 XtraUserControl 的獨立控件,暴露 Text(顯示名)、Value(ID值)、EditValueChanged 事件,實現設計期拖拽、運行期屬性賦值/取值、事件聯動的全周期易用性。

用戶控件設計視圖

三、 核心控件代碼實現

1. 所屬公司控件(CompanyControl)


public partial class CompanyControl : XtraUserControl {
    public event EventHandler EditValueChanged;
    public CompanyControl() {
        InitializeComponent();
        this.txtCompany.EditValueChanged += new EventHandler(txtCompany_EditValueChanged);
    }
    void txtCompany_EditValueChanged(object sender, EventArgs e) {
        if (EditValueChanged != null) EditValueChanged(sender, e);
    }

    public void Init() {
        DataTable dt = DataTableHelper.CreateTable("ImageIndex|int,ID,PID,Name");
        List<OUInfo> list = BLLFactory<OU>.Instance.GetGroupCompany();
        foreach (OUInfo info in list) {
            DataRow dr = dt.NewRow();
            dr["ImageIndex"] = Portal.gc.GetImageIndex(info.Category); // 圖標索引
            dr["ID"] = info.ID.ToString();
            dr["PID"] = info.PID.ToString();
            dr["Name"] = info.Name;
            dt.Rows.Add(dr);
        }
        // 關鍵屬性配置
        this.treeListLookUpEdit1TreeList.SelectImageList = this.imageList2;
        this.treeListLookUpEdit1TreeList.StateImageList = this.imageList2;
        this.txtCompany.Properties.TreeList.KeyFieldName = "ID";
        this.txtCompany.Properties.TreeList.ParentFieldName = "PID";
        this.txtCompany.Properties.DataSource = dt;
        this.txtCompany.Properties.ValueMember = "ID";
        this.txtCompany.Properties.DisplayMember = "Name";
    }

    // 重寫 Text 獲取顯示名
    public override string Text { get { return this.txtCompany.Text; } set { this.txtCompany.Text = value; } }
    // Value 獲取/設置 ID
    public string Value {
        get {
            if (this.txtCompany.EditValue == null || this.txtCompany.EditValue.ToString() == "0") return "-1";
            return this.txtCompany.EditValue.ToString();
        }
        set { this.txtCompany.EditValue = value; }
    }
}

2. 所屬部門控件(DeptControl)

邏輯類似,差異在於 Init() 接收 ParentOuID(公司ID)參數,查詢該公司下的部門數據,並在數據源首行插入「無」選項(ID=0, PID=-1)避免樹形嵌套顯示異常。


public string ParentOuID { get; set; }
public void Init() {
    DataTable dt = DataTableHelper.CreateTable("ImageIndex|int,ID,PID,Name,HandNo,Category,Address,Note");
    if (!string.IsNullOrEmpty(ParentOuID)) {
        List<OUInfo> list = BLLFactory<OU>.Instance.GetAllOUsByParent(ParentOuID.ToInt32());
        foreach (OUInfo info in list) { /* 填充行 */ }
    }
    // 插入「無」選項
    DataRow dr = dt.NewRow();
    dr["ID"] = "0"; dr["PID"] = "-1"; dr["Name"] = "無";
    dt.Rows.InsertAt(dr, 0);
    // 配置屬性同 CompanyControl
    this.txtDept.Properties.TreeList.KeyFieldName = "ID";
    this.txtDept.Properties.TreeList.ParentFieldName = "PID";
    this.txtDept.Properties.DataSource = dt;
    this.txtDept.Properties.ValueMember = "ID";
    this.txtDept.Properties.DisplayMember = "Name";
}

四、 主編輯界面集成與級聯事件處理

在 FrmEditUser 中拖入兩個控件,僅需處理值變化事件實現級聯:


public partial class FrmEditUser : BaseEditForm {
    public FrmEditUser() {
        InitializeComponent();
        this.txtCompany.EditValueChanged += new EventHandler(txtCompany_EditValueChanged);
        this.txtDept.EditValueChanged += new EventHandler(txtDept_EditValueChanged);
    }

    void txtCompany_EditValueChanged(object sender, EventArgs e) {
        if (!string.IsNullOrEmpty(this.txtCompany.Value)) {
            txtDept.ParentOuID = this.txtCompany.Value; // 傳遞選中公司ID
            txtDept.Init(); // 重新加載部門樹
        }
    }

    void txtDept_EditValueChanged(object sender, EventArgs e) {
        if (!string.IsNullOrEmpty(txtDept.Value)) {
            InitManagers(txtDept.Value.ToInt32()); // 加載該部門人員作為直屬經理備選
        }
    }

    // 界面賦值
    this.txtCompany.Value = info.Company_ID;
    this.txtDept.Value = info.Dept_ID;
    // 界面取值
    info.Dept_ID = txtDept.Value;
    info.DeptName = txtDept.Text;
    info.Company_ID = txtCompany.Value;
    info.CompanyName = txtCompany.Text;
}

五、 傳統Winform(非DevExpress)替代方案

若項目不使用DevExpress,推薦Brad Smith開源的 ComboTreeBox 控件(官網),效果近似,節點操作類似 TreeView,通過 ComboTreeNode 構建樹形。


private void Form1_Load(object sender, EventArgs e) {
    this.comboTreeBox1.Nodes.Clear();
    ComboTreeNode parentNode = new ComboTreeNode { Text = "愛奇迪集團" };
    parentNode.Nodes.Add("gz", "廣州分公司");
    parentNode.Nodes["gz"].ImageIndex = 1;
    ComboTreeNode bjNode = new ComboTreeNode { Name = "bj", Text = "北京分公司", ImageIndex = 1, FontStyle = FontStyle.Bold };
    bjNode.Nodes.Add("財務部"); bjNode.Nodes.Add("市場部"); bjNode.Nodes.Add("人力資源部");
    parentNode.Nodes.Add(bjNode);
    this.comboTreeBox1.Nodes.Add(parentNode);
    comboTreeBox1.ExpandAll();
}

ComboTreeBox效果演示

CodeProject上亦有 可定製ComboBox下拉 方案,但易用性略遜。

六、 總結

本文展示了基於DevExpress TreeListLookupEdit 的級聯下拉樹最佳實踐:用戶控件封裝隔離複雜度、KeyFieldName/ParentFieldName 構建樹形關系、ImageIndex 賦予視覺區分度、ValueMember/DisplayMember 分離數值與顯示、事件鏈路實現多級聯動。傳統Winform項目可引用 ComboTreeBox 實現同等體驗。此模式廣泛適用於「省市區」「分類品牌」「機構部門」等一切樹形級聯選擇場景。

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