程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Winform開發框架之權限管理系統改進的經驗總結(1)TreeListLoo

Winform開發框架之權限管理系統改進的經驗總結(1)TreeListLoo

編輯:關於.NET

最近一直在做一些技術性的研究和框架改進工作,博客也落下好幾天沒有更新了,也該是時候靜下心 來,總結這段時間的一些技術改進的經驗了。和上一階段的CRM系統開發和技術研究一樣,我都喜歡在一 個項目或者模塊完成後,做一些相關的總結性工作,記錄下前一階段的技術腳印,希望給自己留下一個 腳印快照,同時給讀者了解自己的技術動向外,也有所收獲。本隨筆主要介紹在下拉列表中展示一個列 表,以便實現數據結構的良好展示,並能快速選定所需的節點,這個就是TreeListLookupEdit控件的使 用。

1、界面效果展示

首先我們來看看我的Winform開發框架之權限管理系統模塊改進完善後的主界面,然後在介紹其中用 到的功能點,以及技術實現。

系統用戶信息管理界面如下所示。

其中用戶信息編輯界面如下所示。

其中編輯用戶信息的界面包括了所屬公司、所屬部門、直屬經理三個輸入的內容,為了減少數據量的 顯示,這幾個輸入框是通過級聯的方式進行展示,也就是說,先選定所屬公司,然後在所屬公司中列出 該公司的部門列表,選定部門後,再通過獲取指定部門的人員信息,作為直屬經理的人員展示。

了解這些邏輯關系後,我們來看看所屬公司的列表展示,如下所示。

選定了所屬公司後,所屬部門就根據公司來進行過濾了,如下所示。

通過公司和部門的條件,我們就可以列出有限的人員列表,作為直屬經理的人員列表了,這個列表使 用普通的下拉列表展示即可,在此不再贅述。

以上的樹狀結構的下拉列表,在DevExpress控件中是通過TreeListLookupEdit控件進行實現的。

2、基於DevExpress控件的功能實現及代碼展示

由於這些所屬公司、所屬部門的功能模塊,一般需要不少代碼進行處理,為了更好重用這些模塊,我 們通過用戶控件的封裝方式進行,然後在數據編輯界面上,通過拖動控件方式即可實現布局,並只需要 設置或者訪問某個屬性即可,封裝的用戶界面控件如下所示。

1)所屬公司控件代碼

所屬公司是一個用戶控件,讓其繼承自XtraUserControl即可,為了在選擇內容後觸發值的變化事件 ,我們定義了一個事件EventHandler EditValueChanged,這樣我們在內部控件的值變化的時候,可以通 知外部的界面進行處理。

public partial class CompanyControl : XtraUserControl
    {
        /// <summary>
        /// 選擇的值發生變化的時候
        /// </summary>
        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);
            }
        }

為了實現列表數據的綁定,以及增加圖標作為區分節點,TreeListLookupEdit控件的數據綁定操作是 這個控件的核心所在。

在下面的代碼邏輯裡面,我們通過獲取公司列表,然後把它轉換為一個DataTable,並根據集團、公 司的層次給予不同的圖標,綁定數據,並設置好控件的KeyFieldName、ParentFieldName、ValueMember 、DisplayMember幾個重要屬性即可,如下所示。

/// <summary>
        /// 初始化數據
        /// </summary>
        public void Init()
        {
            DataTable dt = DataTableHelper.CreateTable("ImageIndex|int,ID,PID,Name");
            List<OUInfo> list = BLLFactory<OU>.Instance.GetGroupCompany();
            DataRow dr = null;
            foreach (OUInfo info in list)
            {
                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屬性和一個Value屬性 。我們需要重載Text屬性,用來獲取或設置所屬公司的名稱;添加一個Value屬性,用來獲取所屬公司的 ID,如下所示。

/// <summary>
        /// 公司名稱
        /// </summary>
        public override string Text
        {
            get
            {
                return this.txtCompany.Text;
            }
            set
            {
                this.txtCompany.Text = value;
            }
        }
    
        /// <summary>
        /// 公司ID
        /// </summary>
        public string Value
        {
            get
            {
                string result = "-1";
                if (this.txtCompany.EditValue == null || this.txtCompany.EditValue.ToString() == "0")
                {
                    result = "-1";
                }
                else
                {                  
                    result = this.txtCompany.EditValue.ToString();
                }
                return result;
            }
            set
            {
                this.txtCompany.EditValue = value;
            }
        }

2)所屬部門的控件代碼

所屬部門的代碼邏輯和所屬公司差不多,唯一不同的是,所屬部門需要一個上級的部門標識(公司ID )作為數據的過濾獲取,如下所示。

/// <summary>
        /// 初始化部門信息
        /// </summary>
        public void Init()
        { 
            //InitUpperOU
            DataTable dt = DataTableHelper.CreateTable("ImageIndex|int,ID,PID,Name,HandNo,Category,Address,Note");
            DataRow dr = null;
    
            if (!string.IsNullOrEmpty(ParentOuID))
            {
                List<OUInfo> list = BLLFactory<OU>.Instance.GetAllOUsByParent(ParentOuID.ToInt32());
                foreach (OUInfo info in list)
                {
                    dr = dt.NewRow();
                    dr["ImageIndex"] = Portal.gc.GetImageIndex(info.Category);
                    dr["ID"] = info.ID.ToString();
                    dr["PID"] = info.PID.ToString();
                    dr["Name"] = info.Name;
                    dr["HandNo"] = info.HandNo;
                    dr["Category"] = info.Category;
                    dr["Address"] = info.Address;
                    dr["Note"] = info.Note;
                    dt.Rows.Add(dr);
                }
            }
            //增加一行空的
            dr = dt.NewRow();
            dr["ID"] = "0"; //使用0代替-1,避免出現節點的嵌套顯示,因為-1已經作為了一般節點的頂級標識
            dr["PID"] = "-1";
            dr["Name"] = "無";
            dt.Rows.InsertAt(dr, 0);
    
            //設置圖形序號
            this.treeListLookUpEdit1TreeList.SelectImageList = this.imageList2;
            this.treeListLookUpEdit1TreeList.StateImageList = this.imageList2;
    
            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";
        }

3)主界面的控件使用

封裝好所屬公司和所屬部門的控件後,我們就可以通過在工具箱裡面拖動控件到主編輯界面裡面去了 ,這樣我們只需要簡單對控件進行設置和賦值即可實現,減少對控件邏輯過多的代碼處理。

數據編輯界面中,控件的使用代碼如下所示。

a)界面賦值操作

                   this.txtCompany.Value = info.Company_ID;
                   this.txtDept.Value = info.Dept_ID;

b)界面數據獲取操作

           info.Dept_ID = txtDept.Value;
           info.DeptName = txtDept.Text;
           info.Company_ID = txtCompany.Value;
           info.CompanyName = txtCompany.Text;

查看本欄目

c)界面事件的處理操作

由於界面上兩個控件是級聯的關系,因此需要處理他們控件的值發生變化的事件,如下所示。

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;
                txtDept.Init();
            }
        }
    
        void txtDept_EditValueChanged(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(txtDept.Value))
            {
                //獲取所屬部門後,就通過部門ID來初始化直屬經理的人員列表
                InitManagers(txtDept.Value.ToInt32());
            }
        }
.................

3、基於傳統Winform界面的控件實現

上面的介紹內容是基於DevExpress的控件組進行功能實現的,有些人可能會問,我使用傳統樣式的界 面控件,這種效果如何實現呢,其實如果是使用內置的控件,是比較困難實現這個效果的,但是這樣的 界面控件有很多人開發好組件可以利用的,我在做這個模塊的時候,也考慮到了這一點,因此也針對這 些做了一些搜索查詢,發現國外有一個同行封裝的控件做的非常不錯,地址是http://www.brad- smith.info/blog/archives/477,上面的效果基本上沒問題的。這個人的博客和下載的例子裡面,沒有 使用Demo的代碼,我自己根據控件的屬性進行了一個Demo例子的編寫,效果和代碼如下所示。

總體來說,這個控件實現的效果還是非常不錯的,例子代碼如下所示,其節點和TreeView的操作類似 ,通過ComboTreeNode對象進行添加即可。

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

除了這個可以實現傳統界面效果的下拉樹展現外,CodeProject上的 http://www.codeproject.com/Articles/25471/Customizable-ComboBox-Drop-Down這篇文字實現的效果 也還不錯。

不過可能沒有上面的那個效果好一點。

4、總結

以上這些就是關於級聯下拉列表,並在下拉列表裡面展示層次關系的樹形結構的功能實現和核心代碼 的操作,本隨筆介紹了基於DevExpress樣式和傳統樣式兩種方案的實現過程,重點對DevExpress控件中 的TreeListLookupEdit控件的實現進行介紹,希望大家能夠在實際工作中用上。

伍華聰  http://www.iqidi.com

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved