WPF+通過配置文件生成菜單(Menu)+源碼


這個月做項目,遇到過一個通過配置文件來生成菜單的解決方案,感覺挺優雅的,特地放到博客園來,以饗讀者。

說來慚愧,以前做的項目都沒有這樣用過,都是固定死了。如果后續有需要加入菜單,還得在重新修改UI,然后提交code,才OK。但是如果通過配置文件的方式進行操作,則可以不用動code,只需要修改配置文件即可。

有興趣的可以往下看,不難,很簡單!~

先看下這次demo的結構:

1。生成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格式文件。

ParentMenuId=0表示這是父類,也就是一級菜單!如果是“1”則表示二級菜單,其它的余此類推。

FormName:表示窗體的路徑

MenuName:表示這個窗體所對於的后台邏輯代碼!這是一個類繼承MenuBase類!

MenuID:就是一個每個Menu的ID,在MenuName子類的時候,需要指定。

2。兩個實體類:MenuInfo和MenuItemInfo

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文件里的字段相對應!

3.。所有Menu的基類---MenuBase

先看代碼:

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控件中。否則,彈出框!

應該說以上就是一些核心的代碼。

4.。怎么用呢?

怎么使用呢?很簡單,在我們的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);
            }
        }
    }

就是一些綁定操作!~

5.。結果

 

匆忙寫的,不懂的可以在討論哈!~晚安咯 各位大神!

猛擊源碼下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM