Winform界面中實(shí)現(xiàn)菜單列表的動(dòng)態(tài)個(gè)性化配置管理方法
在我們一般的應(yīng)用系統(tǒng)里面,由于系統(tǒng)是面向不同類型的用戶,我們所看到的菜單會(huì)越來(lái)越多,多一點(diǎn)的甚至上百個(gè),但是我們實(shí)際工作接觸的菜單可能就是那么幾個(gè),那么對(duì)于這種龐大的菜單體系,尋找起來(lái)非常不便。因此對(duì)菜單的個(gè)性化配置就顯得尤為重要,本篇隨筆就是基于這樣的理念,提供用戶對(duì)可見(jiàn)菜單進(jìn)行一個(gè)動(dòng)態(tài)配置,只選自己喜歡、常用的菜單顯示出來(lái)即可,菜單的配置存儲(chǔ)在數(shù)據(jù)庫(kù)里面,在不同的客戶端體驗(yàn)都是一樣。本篇隨筆主要介紹實(shí)現(xiàn)這樣的功能的一個(gè)完整思路,部分代碼邏輯可供參考。
1、 菜單列表的動(dòng)態(tài)個(gè)性化配置的過(guò)程
在我們有些軟件里面,我們可能在界面上頂部放置菜單,也可能在界面的左側(cè)放置樹(shù)形列表菜單,這種情況都有可能,本篇摘取其中之一,左側(cè)菜單進(jìn)行一個(gè)介紹菜單的配置處理。
例如我們?cè)谧髠?cè)根據(jù)用戶權(quán)限展示相關(guān)的菜單信息,動(dòng)態(tài)生成整個(gè)列表展示,大致的界面效果如下所示。
然后在功能列表上提供一個(gè)右鍵的菜單進(jìn)行菜單的刷新、配置管理,如下界面所示。
通過(guò)配置功能,我們讓用戶進(jìn)入一個(gè)配置管理界面,在其中配置顯示自己感興趣的菜單,然后進(jìn)行保存即可,保存后同時(shí)刷新界面的功能菜單顯示。
以上幾個(gè)界面效果就是為了介紹整個(gè)菜單配置管理的一般過(guò)程,之所以把界面效果放在前面介紹,就是能夠讓我們有一個(gè)類似原型設(shè)計(jì)方式的感性認(rèn)識(shí),了解了相關(guān)的處理過(guò)程,我們就可以著手通過(guò)編碼的方式來(lái)實(shí)現(xiàn)這個(gè)處理邏輯了。
2、菜單動(dòng)態(tài)個(gè)性化配置的功能實(shí)現(xiàn)
上面介紹了大概的界面效果,有了參考,我們可以把它的實(shí)現(xiàn)思路通過(guò)代碼實(shí)現(xiàn)出來(lái)。
1)參數(shù)的數(shù)據(jù)存儲(chǔ)
首先我們需要了解,用戶配置可以通過(guò)XML保存在本地,也可以通過(guò)數(shù)據(jù)庫(kù)存儲(chǔ)保存在服務(wù)器,后者在分布式的客戶端的時(shí)候,可以處處一樣,這樣就不會(huì)造成體驗(yàn)上的差異,因此我們這里采用存儲(chǔ)在數(shù)據(jù)庫(kù)的方案。
這個(gè)存儲(chǔ)我們沿用我之前介紹過(guò)的配置管理組件(SettingsProvider.net),我在隨筆《Winform開(kāi)發(fā)框架之參數(shù)配置管理功能實(shí)現(xiàn)-基于SettingsProvider.net的構(gòu)建》中對(duì)它的使用進(jìn)行了詳細(xì)的介紹。
這個(gè)配置管理組件SettingsProvider.net使用起來(lái)也是比較方便的,可以選擇存儲(chǔ)在本地的對(duì)象,也可以選擇存儲(chǔ)在數(shù)據(jù)庫(kù)的存儲(chǔ)對(duì)象。
首先我們先定義一個(gè)存儲(chǔ)的參數(shù)類,這個(gè)是使用這個(gè)組件所必須的存儲(chǔ)對(duì)象信息,如下代碼所示。
/// <summary>
/// 用來(lái)控制人員管理顯示菜單的參數(shù)配置
/// </summary>
public class UserMenuParameter
{
[DefaultValue("")]
[Description("用戶ID")]
public string UserID { get; set; }
[Description("用戶設(shè)置可見(jiàn)的菜單")]
public Dictionary<string, bool> VisibleDict { get; set; }
}
需要獲取或存儲(chǔ)這個(gè)對(duì)象信息的時(shí)候,我們初始化幾個(gè)管理類,如下代碼所示。
//參數(shù)存儲(chǔ)所需的相關(guān)對(duì)象 private SettingsProvider settings; private ISettingsStorage store; private UserMenuParameter parameter;
然后在配置管理界面窗體里面,初始化這幾個(gè)對(duì)象,如下代碼所示。
// PortableStorage: 在運(yùn)行程序目錄創(chuàng)建一個(gè)setting的文件記錄參數(shù)數(shù)據(jù) // DatabaseStorage:在數(shù)據(jù)庫(kù)TB_UserParameter表存儲(chǔ)用戶配置參數(shù) store = new DatabaseStorage(LoginUserInfo.ID); settings = new SettingsProvider(store); parameter = settings.GetSettings<UserMenuParameter>();
這樣我們就可以根據(jù)用戶的ID,獲取對(duì)應(yīng)記錄的信息并轉(zhuǎn)換為相關(guān)的對(duì)象了,如果我們需要把修改的信息寫會(huì)到存儲(chǔ)介質(zhì)里面,代碼如下所示。
try
{
parameter = settings.GetSettings<UserMenuParameter>();
parameter.VisibleDict = dict;
parameter.UserID = LoginUserInfo.ID;
settings.SaveSettings<UserMenuParameter>(parameter);
ProcessDataSaved(sender, e);//觸發(fā)外部事件
this.DialogResult = System.Windows.Forms.DialogResult.OK;
}
catch (Exception ex)
{
LogHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
return;
}
2)配置管理界面的實(shí)現(xiàn)
解決了參數(shù)的獲取及存儲(chǔ)功能后,我們需要編寫一個(gè)界面來(lái)管理用戶的菜單配置,也就是我們前面介紹的菜單配置管理界面。
我們這個(gè)界面的定義代碼如下所示。
其中參數(shù)的數(shù)據(jù)存儲(chǔ)就是應(yīng)用了前面介紹的代碼,這里需要根據(jù)用戶的配置項(xiàng)初始化樹(shù)形菜單的顯示處理,通過(guò)InitTree的函數(shù)實(shí)現(xiàn)菜單的顯示。
在顯示菜單前,我們先介紹一下功能菜單顯示的規(guī)則,僅當(dāng)參數(shù)存在對(duì)應(yīng)記錄,并且該記錄顯式設(shè)置不可見(jiàn),菜單才不可見(jiàn),否則默認(rèn)菜單是可以看到的。
這樣確保了,在參數(shù)沒(méi)有配置前,所有的菜單對(duì)當(dāng)前用戶是可見(jiàn)的,只有用戶設(shè)置為不不可見(jiàn),該菜單才不顯示為不可見(jiàn)。
/// <summary>
/// 獲取菜單是否可見(jiàn)。
/// 僅當(dāng)參數(shù)存在對(duì)應(yīng)記錄,并且該記錄顯式設(shè)置不可見(jiàn),菜單才不可見(jiàn),否則默認(rèn)菜單是可以看到的。
/// </summary>
/// <param name="id">菜單ID</param>
/// <returns></returns>
private bool GetVisibleMenu(string id)
{
bool result = true;
if (parameter != null)
{
var dict = parameter.VisibleDict;
if(dict != null && dict.ContainsKey(id))
{
result = dict[id];
}
}
return result;
}
顯示菜單的相關(guān)處理邏輯,就是根據(jù)上面的判斷,然后確定是否勾選記錄,如下代碼所示。
存儲(chǔ)用戶勾選的記錄的時(shí)候,我們需要遍歷整個(gè)樹(shù)節(jié)點(diǎn),判斷勾選了那些選項(xiàng),然后把它保存數(shù)據(jù)庫(kù)即可。
/// <summary>
/// 遞歸獲取選中的樹(shù)節(jié)點(diǎn)集合
/// </summary>
/// <param name="node">樹(shù)節(jié)點(diǎn)</param>
/// <param name="dict">字典集合</param>
/// <returns></returns>
private Dictionary<string, bool> GetTreeSelection(TreeNode node, Dictionary<string, bool> dict)
{
if (node.Tag != null)
{
var check = node.Checked;
var menuId = string.Concat(node.Tag);
if(!dict.ContainsKey(menuId))
{
dict.Add(menuId, check);
}
}
foreach (TreeNode child in node.Nodes)
{
GetTreeSelection(child, dict);
}
return dict;
}
參數(shù)的保存操作如下所示。
/// <summary>
/// 保存用戶配置信息
/// </summary>
private void btnOK_Click(object sender, EventArgs e)
{
//獲取用戶勾選的樹(shù)列表,存放在字典集合里面
var dict = new Dictionary<string, bool>();
foreach(TreeNode node in this.treeView1.Nodes)
{
GetTreeSelection(node, dict);
}
try
{
//重新獲取參數(shù)信息,并設(shè)置新值后保存
parameter = settings.GetSettings<UserMenuParameter>();
parameter.VisibleDict = dict;
parameter.UserID = LoginUserInfo.ID;
settings.SaveSettings<UserMenuParameter>(parameter);
ProcessDataSaved(sender, e);//觸發(fā)外部事件
this.DialogResult = System.Windows.Forms.DialogResult.OK;
}
catch (Exception ex)
{
LogHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
return;
}
}
3)主界面的相關(guān)處理
以上處理完成后,我們?cè)谥鹘缑娴墓ぞ邫谟益I菜單添加一個(gè)菜單項(xiàng),用來(lái)進(jìn)入配置界面的,如下邏輯代碼所示。
private void tool_MenuSetting_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
MenuSetting();
}
/// <summary>
/// 配置菜單項(xiàng)
/// </summary>
private void MenuSetting()
{
FrmMenuSetting dlg = new FrmMenuSetting();
dlg.OnDataSaved += (s, arg) =>
{
//用戶保存參數(shù)后,提示用戶更新樹(shù)形列表
InitToolbar();
};
dlg.ShowDialog();
}
這樣界面配置參數(shù)并保存后,界面的樹(shù)形菜單會(huì)及時(shí)得到更新處理。
另外,我們主界面的樹(shù)形列表,也要根據(jù)配置參數(shù)的信息作相關(guān)的調(diào)整,如果用戶配置了不顯示某個(gè)菜單,那么主界面也要根據(jù)配置參數(shù)控制顯示。
3、總結(jié)
以上就是整個(gè)菜單列表的動(dòng)態(tài)個(gè)性化配置管理的整體思路和實(shí)現(xiàn)步驟代碼,主要的界面考量還是以用戶的視覺(jué)來(lái)考慮界面的布局和功能,如果在幾百個(gè)菜單項(xiàng)中尋找?guī)讉€(gè)常用的菜單,每次是一個(gè)比較耗時(shí)無(wú)聊的操作,因此提供一個(gè)個(gè)性化的界面,根據(jù)工作情況的不同,顯示一些和自己相關(guān)的功能即可。
例如有些情況下,我們的菜單顯示,希望通過(guò)工具欄的方式進(jìn)行控制顯示,如下界面效果所示。
那么配置維護(hù)界面還是差不多,只是我們控制工具欄的顯示邏輯有所不同而已,對(duì)于RibbonPage及其功能菜單的動(dòng)態(tài)生成處理如下所示。
本篇隨筆主要還是希望讀者借鑒配置存儲(chǔ)和菜單個(gè)性化管理的思路,具體的邏輯會(huì)因用戶界面的不同,使用的控件不同而有所差異,不過(guò)總體思路是一致的即可。
例如有些參數(shù)的配置管理,可以統(tǒng)一使用一個(gè)配置管理界面進(jìn)行維護(hù),如我之前的隨筆介紹的界面功能一樣。
以上這篇Winform界面中實(shí)現(xiàn)菜單列表的動(dòng)態(tài)個(gè)性化配置管理方法就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持我們。
上一篇:C#使用Gembox.SpreadSheet向Excel寫入數(shù)據(jù)及圖表的實(shí)例
欄 目:C#教程
本文標(biāo)題:Winform界面中實(shí)現(xiàn)菜單列表的動(dòng)態(tài)個(gè)性化配置管理方法
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/5370.html
您可能感興趣的文章
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并打開(kāi)的方法
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新聞效果的方法
- 01-10C#實(shí)現(xiàn)Winform中打開(kāi)網(wǎng)頁(yè)頁(yè)面的方法
- 01-10winform實(shí)現(xiàn)創(chuàng)建最前端窗體的方法
- 01-10C#實(shí)現(xiàn)由四周向中心縮小的窗體退出特效
- 01-10WinForm實(shí)現(xiàn)自定義右下角提示效果的方法
- 01-10Extjs4如何處理后臺(tái)json數(shù)據(jù)中日期和時(shí)間
- 01-10.net2.0+ Winform項(xiàng)目實(shí)現(xiàn)彈出容器層


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什


