這個月作項目,遇到過一個經過配置文件來生成菜單的解決方案,感受挺優雅的,特意放到博客園來,以饗讀者。this
說來慚愧,之前作的項目都沒有這樣用過,都是固定死了。若是後續有須要加入菜單,還得在從新修改UI,而後提交code,才OK。可是若是經過配置文件的方式進行操做,則能夠不用動code,只須要修改配置文件便可。spa
有興趣的能夠往下看,不難,很簡單!~code
先看下此次demo的結構:orm
我用XML格式來存儲,xml
<MenuList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <language>zh-ch</language> <displayName>Simplified_Chinese</displayName> <version>1.0</version> <author>Crystal</author> <MenuItem Name="Trade" HeaderText="交易" MenuId="1" ParentMenuId="0"> <MenuItem Name="CommodityTrade" HeaderText="商品交易" MenuId="11" ParentMenuId="1" FormName="TestMenu.Menu.MenuForm.Trade.CommodityTrade" MenuName="TestMenu.Menu.MenuLogical.Trade.CommodityTradeMenu" OpenType="0"></MenuItem> <MenuItem Name="ConditionTrade" HeaderText="條件下單" MenuId="12" ParentMenuId="1" FormName="TestMenu.Menu.MenuForm.Trade.ConditionTrade" MenuName="TestMenu.Menu.MenuLogical.Trade.ConditionTradeMenu" OpenType="1"></MenuItem> <MenuItem Name="DeliveryTrade" HeaderText="交割申報" MenuId="13" ParentMenuId="1" FormName="TestMenu.Menu.MenuForm.Trade.DeliveryTrade" MenuName="TestMenu.Menu.MenuLogical.Trade.DeliveryTradeMenu" OpenType="1"></MenuItem> </MenuItem> <MenuItem Name="Bank" HeaderText="銀行" MenuId="2" ParentMenuId="0"> <MenuItem Name="BankSign" HeaderText="銀行簽約" MenuId="21" ParentMenuId="2"></MenuItem> <MenuItem Name="BankUnSign" HeaderText="銀行解約" MenuId="22" ParentMenuId="2"></MenuItem> </MenuItem> <MenuItem Name="Fund" HeaderText="資金" MenuId="3" ParentMenuId="0"> <MenuItem Name="FundInOut" HeaderText="出入金" MenuId="31" ParentMenuId="3"></MenuItem> <MenuItem Name="FundTransfer" HeaderText="資金轉移" MenuId="32" ParentMenuId="3"></MenuItem> </MenuItem> <MenuItem Name="Help" HeaderText="幫助" MenuId="9" ParentMenuId="0"> <MenuItem Name="HelpHotKey" HeaderText="熱鍵幫助" MenuId="91" ParentMenuId="9" FormName="" MenuName="" OpenType="0"></MenuItem> <MenuItem Name="HelpNormalQues" HeaderText="常見問題" MenuId="92" ParentMenuId="9" FormName="" MenuName="" OpenType="0"></MenuItem> <MenuItem Name="HelpTelphone" HeaderText="電話服務" MenuId="93" ParentMenuId="9" FormName="" MenuName="" OpenType="0"></MenuItem> <MenuItem Name="HelpProductBook" HeaderText="產品說明書" MenuId="94" ParentMenuId="9" FormName="" MenuName="" OpenType="0"></MenuItem> <MenuItem Name="HelpAbout" HeaderText="關於產品" MenuId="95" ParentMenuId="9"></MenuItem> </MenuItem> </MenuList>
經過上面咱們知道,這是一個標準的XML格式文件。blog
ParentMenuId=0表示這是父類,也就是一級菜單!若是是「1」則表示二級菜單,其它的餘此類推。繼承
FormName:表示窗體的路徑ip
MenuName:表示這個窗體所對於的後臺邏輯代碼!這是一個類繼承MenuBase類!get
MenuID:就是一個每一個Menu的ID,在MenuName子類的時候,須要指定。源碼
MenuInfo:
[Serializable] [XmlRoot("MenuList")] public class MenuInfo { [XmlElement("language")] public string Language { get; set; } [XmlElement("displayName")] public string DisplayName { get; set; } [XmlElement("version")] public string Version { get; set; } [XmlElement("author")] public string Author { get; set; } [XmlElement("MenuItem")] public List<MenuItemInfo> MenuItemList { get; set; } }
MenuItemInfo:
[Serializable] public class MenuItemInfo { [XmlAttribute("Name")] public string Name { get; set; } [XmlAttribute("HeaderText")] public string HeaderText { get; set; } [XmlAttribute("MenuId")] public int MenuId { get; set; } [XmlAttribute("ParentMenuId")] public int ParentMenuId { get; set; } [XmlAttribute("FormName")] public string FormName { get; set; } [XmlAttribute("MenuName")] public string MenuName { set; get; } [XmlAttribute("OpenType")] public int OpenType { get; set; } [XmlElement("MenuItem")] public List<MenuItemInfo> MenuItemList { get; set; } } public enum OpenType { NewForm = 0, //新窗口打開 TabForm = 1, //Tab頁打開 }
就2個Model很簡單,字段都是跟XML文件裏的字段相對應!
先看代碼:
public class MenuBase { public MenuItemInfo menuItemInfo; public MenuBase() { } public MenuBase(int menuId) { this.menuItemInfo = BaseLogic.GetInstanse().MenuList.Find(p => p.MenuId == menuId); } public virtual void Excute(TabControl tabControl) { if (!string.IsNullOrEmpty(this.menuItemInfo.FormName)) { if (this.menuItemInfo.OpenType == (int)OpenType.NewForm) //新窗口打開 { Window billForm = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(this.menuItemInfo.FormName, false) as Window; billForm.ShowDialog(); billForm.Close(); } else if (this.menuItemInfo.OpenType == (int)OpenType.TabForm) //Tab頁打開 { CloseableTabItem tab = null; // TabItem tab = null; if (tabControl.Items.Count > 0) { foreach (CloseableTabItem item in tabControl.Items) { if (item.Name == this.menuItemInfo.Name) { tab = item; break; } } } if (tab == null) { var v = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(this.menuItemInfo.FormName, false); //tab = new TabItem(); tab = new CloseableTabItem(); tab.Name = this.menuItemInfo.Name; tab.Header = this.menuItemInfo.HeaderText; //tab.Tag = this.menuItemInfo.MenuName; tab.Content = v; tabControl.Items.Add(tab); } tab.IsSelected = true; } } } }
這是一個關鍵基類,每個菜單所對應的後臺邏輯頁面,都要繼承MenuBase基類!~
經過上面介紹XML的時候,咱們知道有一個字段是「MenuID」。這個MenuID就是在實現MenuBase的時候,經過base 傳入到基類。而後基類經過下面code進行查詢到相對於頁面信息:
this.menuItemInfo = BaseLogic.GetInstanse().MenuList.Find(p => p.MenuId == menuId);
Execute是一個虛方法,子類進行調用。它有一個參數就是TabControl,若是OpenType(一個枚舉值,是一個窗體仍是一個Tab)的是一個Tab值,那麼就把這個頁面加入到TabControl控件中。不然,彈出框!
應該說以上就是一些核心的代碼。
怎麼使用呢?很簡單,在咱們的XAML中 放入以下東東:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="30px" /> <RowDefinition /> </Grid.RowDefinitions> <Menu Name="MainMenu"> </Menu> <TabControl Name="tabDown" TabStripPlacement="Bottom" Grid.Row="1"> </TabControl> </Grid>
後臺:
public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); } void MainWindow_Loaded(object sender, RoutedEventArgs e) { //加載菜單! if (BaseLogic.GetInstanse().MenuList != null && BaseLogic.GetInstanse().MenuList.Count > 0) { BindMenu(0, null); } } private void BindMenu(int parentId, MenuItem item) { List<MenuItemInfo> list = BaseLogic.GetInstanse().MenuList.FindAll(p => p.ParentMenuId == parentId); if (list != null && list.Count > 0) { foreach (MenuItemInfo info in list) { MenuItem menuItem = new MenuItem(); menuItem.Name = info.Name; menuItem.Header = info.HeaderText; menuItem.Tag = info; menuItem.Click += new RoutedEventHandler(menuItem_Click); if (parentId == 0) { this.MainMenu.Items.Add(menuItem); } else { item.Items.Add(menuItem); } BindMenu(info.MenuId, menuItem); } } } private void menuItem_Click(object sender, RoutedEventArgs e) { MenuItem item = sender as MenuItem; string menuName = ((MenuItemInfo)(item.Tag)).MenuName; //string fullName = menuName; //MenuBase menuBase = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string.Format("ygPlatForm.Logic.MenuLogic.{0}Menu", item.Name), false) as MenuBase; if (menuName != null) { MenuBase menuBase = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(menuName, true) as MenuBase; if (menuBase != null) menuBase.Excute(this.tabDown); } } }
就是一些綁定操做!~
匆忙寫的,不懂的能夠在討論哈!~晚安咯 各位大神!