這幾個月一直忙APP的項目,沒來得及更新項目,想想該抽出時間整理一下開發思路,跟大家分享,同時也希望得到寶貴的建議。
先說一下我們的權限管理的的設計思路,首先一個企業資訊化管理系統一定會用到權限管理, 那麼一個動态的菜單在企業資訊化管理系統占有一定的分量。
下面介紹我的一些思路。
由于原聲的winform界面美觀性不夠, 系統采用dotnetbar第三方控件來輔助程式設計。

首先我們看紅色方框部分為我們的動态子產品功能。這樣我們獲得到了以下幾個資訊, 我們需要記錄子產品功能, 并且需要父子集關系, 那麼對應的我們就需要在資料庫中建立一張表來維護我們的動态菜單子產品。我們舉例命名為BaseModuleTabel, 那麼會有一下的内容,Id ParentId Name,并且由于需要跟不同的使用者有對應的關系, 我們還要建立使用者以及菜單的關系表,來維護使用者與菜單的權限關系。
這裡就不介紹表的設計。我們先來看看在dotnetbar中如何呈現動态菜單邏輯。
我們先從資料庫中擷取到所有菜單子產品。并通過循環便利動态的加載子產品按鈕。 并添加對應的子產品按鈕事件,
1 /// <summary>
2 /// 加載菜單
3 /// </summary>
4 private void LoadMenu()
5 {
6 var parentEntity = _baseModuleBll.Repository().FindEntity("ParentId", "0");
7
8 var result = _baseModuleBll.GetModuleList().Select(p => new BaseTreeViewMenuModel()
9 {
10 Id = p.ModuleId,
11 ParentId = p.ParentId,
12 Name = p.FullName,
13 Class = p.Location,
14 Namespace = StringHelper.SubFirstChart(p.Location, '.'),
15 IsForm = p.Target == "iframe"
16 }).ToList();
17 RibbonTabItem ribbonTabItemFrist = null;
18 var rabbonTabItemEntities = result.Where(p => p.ParentId == parentEntity.ModuleId);
19 foreach (var ribbonTabItemEntity in rabbonTabItemEntities)
20 {
21 var ribbonPanel = new RibbonPanel
22 {
23 Text = ribbonTabItemEntity.Name,
24 Dock = DockStyle.Fill
25 };
26 var ribbonTabItem = new RibbonTabItem
27 {
28 Text = ribbonTabItemEntity.Name,
29 Panel = ribbonPanel
30 };
31 if (ribbonTabItemFrist == null)
32 ribbonTabItemFrist = ribbonTabItem;
33 this.ribbonControlMenu.Controls.Add(ribbonPanel);
34 this.ribbonControlMenu.Items.Add(ribbonTabItem);
35
36 var ribbonBar = new RibbonBar { Text = ribbonTabItemEntity.Name };
37 var buttonItemEntities = result.Where(p => p.ParentId == ribbonTabItemEntity.Id);
38 foreach (var buttonItem in buttonItemEntities.Select(buttonItemEntitiy =>
39 new ButtonItem("ButtonItem" + buttonItemEntitiy.Name)
40 {
41 Text = buttonItemEntitiy.Name,
42 Tag = buttonItemEntitiy
43 }))
44 {
45 buttonItem.Click += ButtonItem_Click;
46 ribbonBar.Items.Add(buttonItem);
47 ribbonPanel.Controls.Add(ribbonBar);
48 }
49 }
50 this.ribbonControlMenu.SelectedRibbonTabItem = ribbonTabItemFrist;
51
52 }
53
54 #endregion
當然我們的架構采用了反射機制來實作元件式開發。通常在一個項目裡,為了降低耦合度,我一邊将子產品力度最小話,并将按一定的規則分類, 處理成摸個子產品,在我們的系統中并不影響彼此開發的同時, 每個成員都可以獨立的去完成自己的小任務, 說句不好聽的, 就算是能力很差的新手,開發出來的耦合度極高的代碼, 通過這樣一種方式,他的影響範圍也緊緊在與他的子產品内, 并不影響其他子產品操作。 僅作為個人的一種方式,當然通過我們的代碼生成器,會生成一定的代碼規範,這雖然能避免一些, 但起不到決定性的作用。 畢竟每個人的能力也是大不相同的。作為PM我們需要做的就是降低項目整體風險,按照規定的項目周期,制定完善的項目計劃,系統子產品劃分力度越大,項目把控的越高。
下面打開點選子產品按鈕來,通過反射來實作對各個子產品的初始化以及加載。代碼效率目前開無太大障礙。當然如果一個子產品dll你要弄個幾百兆,那我也隻能無語了。你的力度相對較小,會跟你反射的時間挂鈎的。
1 /// <summary>
2 /// 打開子產品菜單
3 /// </summary>
4 /// <param name="sender"></param>
5 /// <param name="e"></param>
6 private void ButtonItem_Click(object sender, EventArgs e)
7 {
8 var isOpened = false;
9 var buttonItem = (ButtonItem)sender;
10 var baseTreeViewMenuModel = (BaseTreeViewMenuModel)buttonItem.Tag;
11 if (baseTreeViewMenuModel == null) return;
12 if (!baseTreeViewMenuModel.IsForm) return;
13 if (string.IsNullOrWhiteSpace(baseTreeViewMenuModel.Namespace)) return;
14 //周遊現有的Tab頁面,如果存在,那麼設定為選中即可
15 foreach (var tabitem in
16 superTabControlContent.Tabs.Cast<SuperTabItem>()
17 .Where(tabitem => tabitem.Name == "superTabItem" + baseTreeViewMenuModel.Name))
18 {
19 superTabControlContent.SelectedTab = tabitem;
20 isOpened = true;
21 break;
22 }
23 if (isOpened) return;
24 var dll = Application.StartupPath + "\\" + baseTreeViewMenuModel.Namespace + ".dll";
25 if (!File.Exists(dll)) return;
26 var assembly = Assembly.LoadFrom(dll);
27 var type = assembly.GetType(baseTreeViewMenuModel.Class);
28 if (type == null) return;
29 var form = (FormBase)Activator.CreateInstance(type);
30 form.ModuleId = baseTreeViewMenuModel.Id;
31 form.FormBorderStyle = FormBorderStyle.None;
32 form.TopLevel = false;
33 form.Visible = true;
34 form.Dock = DockStyle.Fill;
35 var superTabItem = superTabControlContent.CreateTab(baseTreeViewMenuModel.Name);
36 superTabItem.Text = baseTreeViewMenuModel.Name;
37 superTabItem.Name = "superTabItem" + baseTreeViewMenuModel.Name;
38 superTabItem.AttachedControl.Controls.Add(form);
39 superTabControlContent.SelectedTab = superTabItem;
40 }
41
42 #endregion
通過以上的代碼我們就可以實作如下圖所示的動态菜單功能 。
分享是美德,要提倡!
Winform快速開發平台系列:
官網連接配接
1.winform快速開發平台 -> 讓有限的資源創造無限的價值!
2.winform快速開發平台 -> 基礎元件之分頁控件
3.winform快速開發平台 -> 綁定ComboBox資料控件
4.winform快速開發平台 -> 工作流元件(仿GooFlow)
5.winform快速開發平台 -> 通用權限管理之動态菜單