在上篇总结随笔《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); }
在开篇说了,用户选择在不少场合会用到,如组织机构的用户选择,角色里面的用户选择,或者流程里面的用户选择等用途。
下面是组织机构里面的主体界面。
在右上角的包含用户区域,单击添加按钮,就会出现前面说到的用户选择对话框,以下所示。