从零开始编写自己的C#框架(18)——Web层后端权限模块——菜单管理
從本章開始,主要講解的是頁面中對框架相關功能的調用方法,比如列表頁面(又分為有層次感列表和普通列表)、編輯頁面、多標簽頁面等,只要熟悉了這些函數的使用方法,那么開發起來就會很便捷了。
?
1、如圖先創建菜單列表與編輯頁面
?
? MenuInfoList.aspx
?View CodeMenuInfoList.aspx.cs
?View Code?
先上列表頁面運行效果圖
2、列表頁代碼說明
在頁面中,可以看到這條工具條,我們打開aspx頁面,找到<f:Toolbar ID="toolBar" runat="server"></f:Toolbar>標簽
1 <f:Toolbar ID="toolBar" runat="server"> 2 <Items> 3 <f:Button ID="ButtonRefresh" runat="server" Text="刷新" Icon="ArrowRefresh" OnClick="ButtonRefresh_Click" CssClass="inline"></f:Button> 4 <f:Button ID="ButtonAdd" runat="server" Text="添加" Icon="Add" OnClick="ButtonAdd_Click"></f:Button> 5 <f:Button ID="ButtonSearch" runat="server" Text="查詢" Icon="Magnifier" OnClick="ButtonSearch_Click"></f:Button> 6 <%--<f:Button ID="ButtonEdit" runat="server" Text="編輯" Icon="BulletEdit" OnClick="ButtonEdit_Click" 7 OnClientClick="if(!F('Panel1_Grid1').getSelectionModel().hasSelection()|| F('Panel1_Grid1').getSelectionModel().getCount()>=2){F.alert('您沒有選擇編輯項或只能選擇一項進行編輯!'); return false; }"> 8 </f:Button>--%> 9 <f:Button ID="ButtonSaveAutoSort" runat="server" Text="自動排序" Icon="ArrowJoin" OnClick="ButtonSaveAutoSort_Click" ConfirmTitle="自動排序提示" ConfirmText="是否對所有數據進行自動排序?"></f:Button> 10 <f:Button ID="ButtonSaveSort" runat="server" Text="保存排序" Icon="Disk" OnClick="ButtonSaveSort_Click"></f:Button> 11 <f:Button ID="ButtonDelete" runat="server" Text="刪除" Icon="Delete" OnClick="ButtonDelete_Click" ConfirmTitle="刪除提示" ConfirmText="是否刪除記錄?" 12 OnClientClick="if (!F('Panel1_Grid1').getSelectionModel().hasSelection() ) { F.alert('刪除時必須選擇一條將要刪除的記錄!'); return false; } if (F('Panel1_Grid1').getSelectionModel().getCount() >= 2) { F.alert('只能選擇一條記錄進行刪除!');return false; }"> 13 </f:Button> 14 </Items> 15 </f:Toolbar>在里面放置的按鍵都會在這里顯示出來,這個標簽的Id必須命名為toolBar,因為在PageBase這個父類的初始化函數OnInit中有下面這段代碼,會自動為放在這里的按鍵進行權限判斷處理,檢查當前用戶是否有對應按鍵的操作權限,沒有操作權限的按鍵自動禁用掉,這樣的話我們在開發時就不用為這些按鍵權限一個個進行賦值,做這么多麻煩的操作了
(灰白色的為已禁用按鍵)
1 #region 設置頁面按鍵權限 2 try 3 { 4 //定義按鍵控件 5 Control btnControl = null; 6 //找到頁面放置按鍵控件的位置 7 ControlCollection controls = MenuInfoBll.GetInstence().GetControls(this.Controls, "toolBar"); 8 //逐個讀取出來 9 for (int i = 0; i < controls.Count; i++) 10 { 11 //取出控件 12 btnControl = controls[i]; 13 //判斷是否除了刷新、查詢和關閉以外的按鍵 14 if (btnControl.ID != "ButtonRefresh" && btnControl.ID != "ButtonSearch" && btnControl.ID != "ButtonClose" && btnControl.ID != "ButtonReset") 15 { 16 //是的話檢查該按鍵當前用戶是否有控件權限,沒有的話則禁用該按鍵 17 ((FineUI.Button)btnControl).Enabled = MenuInfoBll.GetInstence().CheckControlPower(this, btnControl.ID); 18 } 19 } 20 } 21 catch (Exception) { } 22 #endregion?
對于表格的綁定也很方便,我們想顯示那幾列,只要將字段綁定到列表中就可以了,修改字段名稱或添加新字段時,只需要對數據層與邏輯層的代碼重新一鍵生成后,不用修改其他代碼,這里重新綁定就可以顯示出來,非常方便,大家可以試試刪除下面代碼中的幾列或在數據庫添加新字段測試一下就明白了。
1 <f:Grid ID="Grid1" Title="菜單列表" EnableFrame="false" EnableCollapse="true" AllowSorting="true" SortField="Depth" SortDirection="ASC" 2 PageSize="15" ShowBorder="true" ShowHeader="true" AllowPaging="true" runat="server" EnableCheckBoxSelect="True" DataKeyNames="Id" EnableColumnLines="true" 3 OnPageIndexChange="Grid1_PageIndexChange" OnPreRowDataBound="Grid1_PreRowDataBound" OnRowCommand="Grid1_RowCommand"> 4 <Columns> 5 <f:RowNumberField /> 6 <f:BoundField Width="180px" DataField="Name" DataFormatString="{0}" DataSimulateTreeLevelField="Depth" HeaderText="菜單(頁面)名" /> 7 <f:BoundField DataField="Url" HeaderText="訪問路徑" ExpandUnusedSpace="true" /> 8 <f:TemplateField HeaderText="排序" Width="100px"> 9 <ItemTemplate> 10 <asp:TextBox ID="tbSort" runat="server" Width="50px" Text='<%# Eval("Sort") %>' AutoPostBack="false"></asp:TextBox> 11 </ItemTemplate> 12 </f:TemplateField> 13 <f:LinkButtonField HeaderText="是否顯示" Icon="BulletCross" TextAlign="Center" ToolTip="點擊修改是否顯示" ColumnID="IsDisplay" CommandName="IsDisplay" /> 14 <f:LinkButtonField HeaderText="是否頁面" Icon="BulletCross" TextAlign="Center" ToolTip="點擊修改是否頁面" ColumnID="IsMenu" CommandName="IsMenu" /> 15 <f:BoundField DataField="Depth" HeaderText="級別層次" TextAlign="Center" /> 16 <f:LinkButtonField HeaderText="操作" TextAlign="Center" ToolTip="點擊修改當前記錄" ColumnID="ButtonEdit" CommandName="ButtonEdit" /> 17 </Columns> 18 </f:Grid>對于列表的事件,在Grid標簽中,敲一下空格就會彈出可以使用的事件列表出來,只要綁定對應名稱后,在cs文件中添加對應函數就能直接調用,具體大家可以去FineUI官網查看使用例子
? 列表頁中,可以看到<f:Label runat="server" ID="lblSpendingTime" Text=""></f:Label>這個標簽,這是用來顯示列表執行時間的,只需要放上它就會自動顯示列表執行時間:
<f:window>標簽是用來處理顯示和隱藏彈出編輯窗口用的,大家可以根據需要自己修改編輯寬與高
?
?
由于MenuInfoList.aspx.cs必須繼承PageBase類,所以我們必須實現Init()與LoadData()這兩個函數
在列表頁面中,我們需要實現Init()函數,并為當前頁面所調用的邏輯層對象與表格對象進行賦值,如下面代碼。賦值后不少功能就自動實現了,具體請看后面的演示效果。
1 #region 接口函數,用于UI頁面初始化,給邏輯層對象、列表等對象賦值 2 public override void Init() 3 { 4 //邏輯對象賦值 5 bll = MenuInfoBll.GetInstence(); 6 //表格對象賦值 7 grid = Grid1; 8 } 9 #endregion由于本列表頁面要顯示的是有層次感的列表,所以Sort調用的是自定義的代碼(有層次感的列表排序必須先用Depth進行升序排序后,再用Sort排序),同時也去掉了列表中點擊表頭排序的功能(會弄亂層次感列表)
對于表格的綁定、翻頁等功能,我們在邏輯層已生成對應的函數了,所以這里直接調用就可以了,bll.BindGrid(Grid1, InquiryCondition(), sortList);這個是專門用于有層次感列表的
為了保持列表的層次感,所以查詢條件是直接綁定根級別的菜單
1 #region 加載數據 2 /// <summary>讀取數據</summary> 3 public override void LoadData() 4 { 5 //設置排序 6 if (sortList == null) 7 { 8 Sort(); 9 } 10 11 //綁定Grid表格 12 bll.BindGrid(Grid1, InquiryCondition(), sortList); 13 } 14 15 /// <summary> 16 /// 查詢條件 17 /// </summary> 18 /// <returns></returns> 19 private int InquiryCondition() 20 { 21 int value = 0; 22 23 //選擇菜單 24 if (ddlParentId.SelectedValue != "0") 25 { 26 value = ConvertHelper.Cint0(ddlParentId.SelectedValue); 27 } 28 return value; 29 } 30 31 #region 排序 32 /// <summary> 33 /// 頁面表格綁定排序 34 /// </summary> 35 public void Sort() 36 { 37 //設置排序 38 sortList = new List<string>(); 39 sortList.Add(MenuInfoTable.Depth + " asc"); 40 sortList.Add(MenuInfoTable.Sort + " asc"); 41 } 42 #endregion 43 44 #endregion? 查詢效果圖
?
保存排序與自動排序功能(注意觀察菜單名稱與排序值的變化)
在cs代碼中,可以看到,里面并沒有保存排序與自動排序的代碼,因為在父類中已對這些常用功能進行了封裝,所以我們在實現Init()函數時對邏輯層對象與表格對象進行賦值后,就會自動擁有這些功能
未修改
修改排序值
點擊保存排序按鍵
點擊自動排序按鍵
當然對于有父Id的列表自動排序,無需要編寫代碼就會自動實現了,而對于沒有父Id字段的表,我們就需要重寫SaveAutoSort()函數來實現,請看下面重寫代碼
1 /// <summary> 2 /// 保存自動排序 3 /// </summary> 4 public override void SaveAutoSort() 5 { 6 if (bll == null) 7 { 8 Alert.ShowInParent("保存失敗", "邏輯層對象為null,請聯系開發人員給當前頁面的邏輯層對象賦值"); 9 return; 10 } 11 12 if (bll.UpdateAutoSort(this)) 13 { 14 Alert.ShowInParent("保存成功", "保存自動排序成功", "window.location.reload();"); 15 } 16 else 17 { 18 Alert.ShowInParent("保存失敗", "保存自動排序失敗"); 19 } 20 }根據需要,還可以在UpdateAutoSort函數中加上不同的參數,來實現不同條件下自動排序的效果
?
列表屬性綁定說明
在列表中,我們可以看到是否顯示與是否頁面的圖像是可以點擊的,點一下就可以將其改變,如下圖
點擊之前
點擊之后
這個就是在下面代碼中進行綁定的
?View Code而更新狀態的函數MenuInfoBll.GetInstence().UpdateIsDisplay()、MenuInfoBll.GetInstence().UpdateIsMenu(),我們模板里已經生成了,直接調用即可
?
最后一列編輯按鍵,這個根據需要可以放到頂部的工具條里(在前面代碼大家可以看到我將其注釋了),也可以放到這里來,而放到這里的話,則需要在表格綁定的代碼中實現
由于整個權限模塊未開發出來,所以我先將按鍵的權限判斷注釋掉了(//lbfEdit.Enabled = MenuInfoBll.GetInstence().CheckControlPower(this, "ButtonEdit");)
在Grid點擊事件中,打開隱藏的編輯窗口
//打開編輯窗口
????? Window1.IFrameUrl = "MenuInfoEdit.aspx?Id=" + id + "&" + MenuInfoBll.GetInstence().PageUrlEncryptStringNoKey(id + "");
????? Window1.Hidden = false; //顯示窗口
? 在上面的Url鏈接中,我們需要傳遞兩個參數,一個是將要編輯的記錄Id,一個是頁面加密處理參數,通過MenuInfoBll.GetInstence().PageUrlEncryptStringNoKey(id + "")函數來生成對應的頁面加密參數,系統在對密鑰進行識別處理時,會按順序默認對Id、pid、ParentId、Key這幾個值做為密鑰生成值進行識別,具體大家自行研究一下吧。
?
而對于工具欄中的按鍵實現,添加新記錄對應的是Add()函數、編輯記錄對應的是Edit()函數、刪除記錄對應的是Delete(),當然工具欄中按鍵的命名要求必須同上面那幾個一樣,具體實現這里就不再一一細說,大家直接看代碼吧。
?
? 由于時間關系,編輯頁面代碼就不進行解說,大家自己進行研究吧,下面上一張編輯頁面運行后的圖片
?
另外,為了由于權限模塊未完成,所以將相關的權限判斷都注釋掉了,等后面完善后再啟用。
本次更新,除了修改一些小問題外,也修改了CommonBll.cs類的添加用戶訪問頁面記錄函數,以及自定義類UseLogBll.cs類的添加用戶操作日志函數,讓用戶訪問頁面記錄運行起來,當然這個表記錄的不至這些訪問內容,它還會將用戶的增、刪、查、改等所有操作都記錄下來,下面看看效果圖(這個函數會將用戶登陸進系統后每一步訪問都記錄下來,這個要求是來自以前的公司老總,當時做了一個OA系統公司自己用,他看了后就說:OA開發后,如果大家都不登陸不使用那有等于沒有,能不能實現通過后端查看,知道大家有沒有使用。再然后就多了這個功能,呵呵)
?
?
本章內容看起來比較亂,大家最好直接運行解決方案代碼,在瀏覽器中運行查看效果,再結合代碼查看可能會容易理解,還有一點要補充的是,本解決方案不包含extjs代碼,需要大家自行下載放到根目錄里
?
?
? ? 本文轉自 AllEmpty 博客園博客,原文鏈接:http://www.cnblogs.com/EmptyFS/p/3798936.html,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的从零开始编写自己的C#框架(18)——Web层后端权限模块——菜单管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原创:能力强大到能掌控自己人生的女人都是
- 下一篇: js操作样式自动prefix