在上篇總結隨筆《Winform開發框架之權限管理系統改進的經驗總結(1)-TreeListLookupEdit控件的使用》介紹了權限管理模塊的用戶管理部分,其中主要介紹了其中的用戶所屬公司、所屬部門、直屬經理(人員列表)的幾級數據級聯的展現,經過引入TreeListLookupEdit控件,能加強用戶的體驗效果。本篇繼續介紹權限系統模塊中的一些閃光點,介紹組織機構管理裏面選擇用戶的界面設計和實現,用戶選擇在不少場合會用到,如組織機構的用戶選擇,角色裏面的用戶選擇,或者流程裏面的用戶選擇等用途。html
用戶選擇在不少地方須要用到,本篇以組織機構裏面的用戶選擇爲例,介紹用戶選擇的界面效果。咱們知道,用戶通常能夠按組織機構進行分類,也能夠按照角色進行分類,所以咱們須要結合二者進行快速展現用戶的層次關係,界面效果以下所示。node
在上面的界面分爲三個部分:左邊主要是機構和角色的展現;右邊則是經過列表控件進行展現,並能夠進行勾選的操做;底部則是已選用戶的列表展現(能夠移除)。數據庫
組織機構自己設計就是一個有層次關係的樹,所以它能夠經過遞歸函數進行展示,展現方式可使用傳統樣式的TreeView控件或者DevExpress樣式的TreeList控件,不過我傾向於使用TreeView,以爲這個線狀的層次關係更美觀一些,遞歸展現結構樹的代碼以下所示。框架
private void InitDeptTree() { this.treeDept.BeginUpdate(); this.treeDept.Nodes.Clear(); TreeNode node = new TreeNode(); node.Text = "全部部門"; List<OUNodeInfo> list = BLLFactory<OU>.Instance.GetTree(); AddDept(list, node); this.treeDept.Nodes.Add(node); this.treeDept.ExpandAll(); this.treeDept.EndUpdate(); } private void AddDept(List<OUNodeInfo> list, TreeNode treeNode) { foreach (OUNodeInfo ouInfo in list) { TreeNode deptNode = new TreeNode(); deptNode.Text = ouInfo.Name; deptNode.Tag = ouInfo.ID; deptNode.ImageIndex = Portal.gc.GetImageIndex(ouInfo.Category); deptNode.SelectedImageIndex = Portal.gc.GetImageIndex(ouInfo.Category); treeNode.Nodes.Add(deptNode); AddDept(ouInfo.Children, deptNode); } }
角色樹不是一個遞歸的關係,所以只須要按列表展現便可,展現代碼以下所示。函數
private void InitRoleTree() { this.treeRole.BeginUpdate(); this.treeRole.Nodes.Clear(); TreeNode node = new TreeNode(); node.Text = "全部角色"; List<RoleInfo> list = BLLFactory<Role>.Instance.GetAll(); foreach (RoleInfo info in list) { TreeNode roleNode = new TreeNode(); roleNode.Text = info.Name; roleNode.Tag = info.ID; roleNode.ImageIndex = 5; roleNode.SelectedImageIndex = 5; node.Nodes.Add(roleNode); } this.treeRole.Nodes.Add(node); this.treeRole.ExpandAll(); this.treeRole.EndUpdate(); }
角色列表大概效果以下所示。this
右邊其實能夠經過通常的GridView進行展現,但爲了更好的封裝和使用,我使用個人Winform分頁控件中的WinGridview對象進行展現,這樣使用起來更簡便。spa
public partial class FrmSelectUser : BaseForm { public FrmSelectUser() { InitializeComponent(); this.winGridView1.ShowCheckBox = true; this.winGridView1.ShowExportButton = false; this.winGridView1.ShowLineNumber = true; this.winGridView1.BestFitColumnWith = false;//是否設置爲自動調整寬度,false爲不設置 this.winGridView1.OnRefresh += new EventHandler(winGridView1_OnRefresh); this.winGridView1.gridView1.DataSourceChanged += new EventHandler(gridView1_DataSourceChanged); if (!this.DesignMode) { InitDeptTree(); InitRoleTree(); } }
綁定數據是經過左邊的樹進行條件檢索的,所以能夠經過獲取組織機構或者角色的節點數據進行查詢,咱們經過判斷組織機構樹節點或者角色樹節點是否選中來判斷便可,具體列表綁定的代碼以下所示。設計
private void BindGridData() { List<UserInfo> list = new List<UserInfo>(); if (this.treeDept.SelectedNode != null && this.treeDept.SelectedNode.Tag != null) { int ouId = this.treeDept.SelectedNode.Tag.ToString().ToInt32(); list = BLLFactory<User>.Instance.FindByDept(ouId); } else if (this.treeRole.SelectedNode != null && this.treeRole.SelectedNode.Tag != null) { int roleId = this.treeRole.SelectedNode.Tag.ToString().ToInt32(); list = BLLFactory<User>.Instance.GetUsersByRole(roleId); } //entity this.winGridView1.DisplayColumns = "HandNo,Name,FullName,Title,MobilePhone,OfficePhone,Email,Gender,QQ,Note"; this.winGridView1.ColumnNameAlias = BLLFactory<User>.Instance.GetColumnNameAlias();//字段列顯示名稱轉義 this.winGridView1.DataSource = new WHC.Pager.WinControl.SortableBindingList<UserInfo>(list); }
單用戶勾選列表的複選框的時候,該行的數據會被選中,咱們最後要獲取用戶的勾選記錄(經過WinGridview控件的GetCheckedRows方法獲取),而後獲取對應的數據,添加到關聯關係的數據庫便可,具體代碼以下所示。code
private void btnAddUser_Click(object sender, EventArgs e) { List<int> list = this.winGridView1.GetCheckedRows(); foreach(int rowIndex in list) { string ID = this.winGridView1.GridView1.GetRowCellDisplayText(rowIndex, "ID"); string Name= this.winGridView1.GridView1.GetRowCellDisplayText(rowIndex, "Name"); string FullName = this.winGridView1.GridView1.GetRowCellDisplayText(rowIndex, "FullName"); string displayname = string.Format("{0}({1})", FullName, Name); if (!this.SelectUserDict.ContainsKey(ID)) { this.SelectUserDict.Add(ID, displayname); } } RefreshSelectItems(); }
在一些場景中,咱們可能須要在多個組織機構和角色中選擇不一樣的用戶,爲了更方便展現咱們選中的記錄,我設計了一個用戶控件(一個刪除按鈕(Button)+標籤控件(Lable))組合便可,以下所示。orm
因爲咱們選擇的內容,無非就是選擇它的人員名稱便可,若是須要,單擊刪除按鈕,讓用戶剔除不須要的人員,所以控件增長一個OnDeleteItem事件用來處理這個刪除操做。
咱們展現多個用戶信息的時候,就是經過構造多個這樣的控件,並動態增長到Panel裏面便可,實現代碼以下所示。
/// <summary> /// 刷新選擇信息 /// </summary> private void RefreshSelectItems() { this.flowLayoutPanel1.Controls.Clear(); foreach (string key in SelectUserDict.Keys) { string info = SelectUserDict[key]; if (!string.IsNullOrEmpty(info)) { UserNameControl control = new UserNameControl(); control.BindData(key, info); control.OnDeleteItem += new UserNameControl.DeleteEventHandler(control_OnDeleteItem); this.flowLayoutPanel1.Controls.Add(control); } } this.lblItemCount.Text = string.Format("當前選擇【{0}】項目", SelectUserDict.Keys.Count); }
在開篇說了,用戶選擇在不少場合會用到,如組織機構的用戶選擇,角色裏面的用戶選擇,或者流程裏面的用戶選擇等用途。
下面是組織機構裏面的主體界面。
在右上角的包含用戶區域,單擊添加按鈕,就會出現前面說到的用戶選擇對話框,以下所示。