你的位置:首页 > ASP.net教程

[ASP.net教程]WPF+通过配置文件生成菜单(Menu)+源码

这个月做项目,遇到过一个通过配置文件来生成菜单的解决方案,感觉挺优雅的,特地放到博客园来,以飨读者。

说来惭愧,以前做的项目都没有这样用过,都是固定死了。如果后续有需要加入菜单,还得在重新修改UI,然后提交code,才OK。但是如果通过配置文件的方式进行操作,则可以不用动code,只需要修改配置文件即可。

有兴趣的可以往下看,不难,很简单!~

先看下这次demo的结构:

1。生成

我用

<MenuList ="http://www.w3.org/2001/ ="http://www.w3.org/2001/> <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>

通过上面我们知道,这是一个标准的

ParentMenuId=0表示这是父类,也就是一级菜单!如果是“1”则表示二级菜单,其它的余此类推。

FormName:表示窗体的路径

MenuName:表示这个窗体所对于的后台逻辑代码!这是一个类继承MenuBase类!

MenuID:就是一个每个Menu的ID,在MenuName子类的时候,需要指定。

2。两个实体类:MenuInfo和MenuItemInfo

MenuInfo:

 [Serializable]  ["MenuList")]  public class MenuInfo  {    ["language")]    public string Language { get; set; }    ["displayName")]    public string DisplayName { get; set; }    ["version")]    public string Version { get; set; }    ["author")]    public string Author { get; set; }    ["MenuItem")]    public List<MenuItemInfo> MenuItemList { get; set; }  }

MenuItemInfo:

 [Serializable]  public class MenuItemInfo  {    ["Name")]    public string Name { get; set; }    ["HeaderText")]    public string HeaderText { get; set; }    ["MenuId")]    public int MenuId { get; set; }    ["ParentMenuId")]    public int ParentMenuId { get; set; }    ["FormName")]    public string FormName { get; set; }    ["MenuName")]    public string MenuName { set; get; }    ["OpenType")]    public int OpenType { get; set; }    ["MenuItem")]    public List<MenuItemInfo> MenuItemList { get; set; }  }  public enum OpenType  {    NewForm = 0,       //新窗口打开    TabForm = 1,       //Tab页打开  }

就2个Model很简单,字段都是跟

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基类!~

通过上面介绍

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.。结果

 

匆忙写的,不懂的可以在讨论哈!~晚安咯 各位大神!

猛击源码下载