WEB开发网
开发学院WEB开发Xml 一个简单的基于XML的模块集成框架 阅读

一个简单的基于XML的模块集成框架

 2006-04-12 11:25:45 来源:WEB开发网   
核心提示:1. 准备一个xml文件xmlmenu 1<Menu> 2 <MenuItem Name="系统管理" AssemblyName="" FormTag="FALSE" AddToolbar="FALSE"> 3

1. 准备一个xml文件

xmlmenu
 1<Menu>
 2   <MenuItem Name="系统管理" AssemblyName="" FormTag="FALSE" AddToolbar="FALSE">
 3     <MenuItem Name="权限管理" ShortCut="" Image="" AssemblyName="" FormTag="FALSE" AddToolButton="FALSE">
 4       <MenuItem Name="系统权限管理" ShortCut="" Image="passWord.png" AssemblyName="HustCAD.IntePLM.WinUI.FrmSysRight,IntePLM.TyRightWinUI" FormTag="TRUE" AddToolButton="FALSE"/>
 5       <MenuItem Name="权限规则定义" ShortCut="" Image="right.png" AssemblyName="HustCAD.IntePLM.WinUI.FrmRightRule,IntePLM.TyRightWinUI" FormTag="TRUE" AddToolButton="FALSE"/>
 6       <MenuItem Name="权限日志" ShortCut="" Image="doc_yellow_edit.png" AssemblyName="HustCAD.IntePLM.WinUI.FrmRightLog,IntePLM.TyRightWinUI" FormTag="TRUE" AddToolButton="FALSE"/>
 7     </MenuItem>
8</Menu>
2.准备一个xml schemal文件来验证xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSpy v2006 sp2 U (http://www.altova.com) by peter (hust) -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
   <xs:element name="Menu">
     <xs:complexType>
       <xs:sequence>
         <xs:element ref="MenuItem" maxOccurs="unbounded"/>
       </xs:sequence>
     </xs:complexType>
   </xs:element>
   <xs:element name="MenuItem">
     <xs:complexType>
       <xs:sequence>
         <xs:element ref="MenuItem" minOccurs="0" maxOccurs="unbounded"/>
       </xs:sequence>
       <xs:attribute name="AddToolButton">
         <xs:simpleType>
           <xs:restriction base="xs:string">
             <xs:enumeration value="TRUE"/>
             <xs:enumeration value="FALSE"/>
           </xs:restriction>
         </xs:simpleType>
       </xs:attribute>
       <xs:attribute name="AddToolbar">
         <xs:simpleType>
           <xs:restriction base="xs:string">
             <xs:enumeration value="TRUE"/>
             <xs:enumeration value="FALSE"/>
           </xs:restriction>
         </xs:simpleType>
       </xs:attribute>
       <xs:attribute name="AssemblyName" type="xs:string" use="required"/>
       <xs:attribute name="FormTag" use="required">
         <xs:simpleType>
           <xs:restriction base="xs:string">
             <xs:enumeration value="TRUE"/>
             <xs:enumeration value="FALSE"/>
           </xs:restriction>
         </xs:simpleType>
       </xs:attribute>
       <xs:attribute name="Image" type="xs:string"/>
       <xs:attribute name="Name" type="xs:string" use="required"/>
       <xs:attribute name="ShortCut" use="optional">
         <xs:simpleType>
           <xs:restriction base="xs:string">
             <xs:enumeration value="F1"/>
             <xs:enumeration value="F2"/>
             <xs:enumeration value="F3"/>
             <xs:enumeration value="F4"/>
             <xs:enumeration value="F5"/>
             <xs:enumeration value="F6"/>
             <xs:enumeration value="F7"/>
             <xs:enumeration value="F8"/>
             <xs:enumeration value="F9"/>
             <xs:enumeration value="F10"/>
             <xs:enumeration value="F11"/>
             <xs:enumeration value="F12"/>
             <xs:enumeration value="Alt0"/>
             <xs:enumeration value="Alt1"/>
             <xs:enumeration value="Alt2"/>
             <xs:enumeration value="Alt3"/>
             <xs:enumeration value="Alt4"/>
             <xs:enumeration value="Alt5"/>
             <xs:enumeration value="Alt6"/>
             <xs:enumeration value="Alt7"/>
             <xs:enumeration value="Alt8"/>
             <xs:enumeration value="Alt9"/>
             <xs:enumeration value="AltBksp"/>
             <xs:enumeration value="AltF1"/>
             <xs:enumeration value="AltF2"/>
             <xs:enumeration value="AltF3"/>
             <xs:enumeration value="AltF4"/>
             <xs:enumeration value="AltF5"/>
             <xs:enumeration value="AltF6"/>
             <xs:enumeration value="AltF7"/>
             <xs:enumeration value="AltF8"/>
             <xs:enumeration value="AltF9"/>
             <xs:enumeration value="AltF10"/>
             <xs:enumeration value="AltF11"/>
             <xs:enumeration value="AltF12"/>
             <xs:enumeration value="AltDownArrow"/>
             <xs:enumeration value="AltUpArrow"/>
             <xs:enumeration value="AltLeftArrow"/>
             <xs:enumeration value="AltRightArrow"/>
             <xs:enumeration value="Ctrl0"/>
             <xs:enumeration value="Ctrl1"/>
             <xs:enumeration value="Ctrl2"/>
             <xs:enumeration value="Ctrl3"/>
             <xs:enumeration value="Ctrl4"/>
             <xs:enumeration value="Ctrl5"/>
             <xs:enumeration value="Ctrl6"/>
             <xs:enumeration value="Ctrl7"/>
             <xs:enumeration value="Ctrl8"/>
             <xs:enumeration value="Ctrl9"/>
             <xs:enumeration value="CtrlA"/>
             <xs:enumeration value="CtrlB"/>
             <xs:enumeration value="CtrlC"/>
             <xs:enumeration value="CtrlD"/>
             <xs:enumeration value="CtrlE"/>
             <xs:enumeration value="CtrlF"/>
             <xs:enumeration value="CtrlG"/>
             <xs:enumeration value="CtrlH"/>
             <xs:enumeration value="CtrlI"/>
             <xs:enumeration value="CtrlJ"/>
             <xs:enumeration value="CtrlK"/>
             <xs:enumeration value="CtrlL"/>
             <xs:enumeration value="CtrlM"/>
             <xs:enumeration value="CtrlN"/>
             <xs:enumeration value="CtrlO"/>
             <xs:enumeration value="CtrlP"/>
             <xs:enumeration value="CtrlQ"/>
             <xs:enumeration value="CtrlR"/>
             <xs:enumeration value="CtrlS"/>
             <xs:enumeration value="CtrlT"/>
             <xs:enumeration value="CtrlU"/>
             <xs:enumeration value="CtrlV"/>
             <xs:enumeration value="CtrlX"/>
             <xs:enumeration value="CtrlY"/>
             <xs:enumeration value="CtrlZ"/>
             <xs:enumeration value="CtrlF1"/>
             <xs:enumeration value="CtrlF2"/>
             <xs:enumeration value="CtrlF3"/>
             <xs:enumeration value="CtrlF4"/>
             <xs:enumeration value="CtrlF5"/>
             <xs:enumeration value="CtrlF6"/>
             <xs:enumeration value="CtrlF7"/>
             <xs:enumeration value="CtrlF8"/>
             <xs:enumeration value="CtrlF9"/>
             <xs:enumeration value="CtrlF10"/>
             <xs:enumeration value="CtrlF11"/>
             <xs:enumeration value="CtrlF12"/>
             <xs:enumeration value="CtrlIns"/>
             <xs:enumeration value="CtrlShift0"/>
             <xs:enumeration value="CtrlShift1"/>
             <xs:enumeration value="CtrlShift2"/>
             <xs:enumeration value="CtrlShift3"/>
             <xs:enumeration value="CtrlShift4"/>
             <xs:enumeration value="CtrlShift5"/>
             <xs:enumeration value="CtrlShift6"/>
             <xs:enumeration value="CtrlShift7"/>
             <xs:enumeration value="CtrlShift8"/>
             <xs:enumeration value="CtrlShift9"/>
             <xs:enumeration value="CtrlShiftA"/>
             <xs:enumeration value="CtrlShiftB"/>
             <xs:enumeration value="CtrlShiftC"/>
             <xs:enumeration value="CtrlShiftD"/>
             <xs:enumeration value="CtrlShiftE"/>
             <xs:enumeration value="CtrlShiftF"/>
             <xs:enumeration value="CtrlShiftG"/>
             <xs:enumeration value="CtrlShiftH"/>
             <xs:enumeration value="CtrlShiftI"/>
             <xs:enumeration value="CtrlShiftJ"/>
             <xs:enumeration value="CtrlShiftK"/>
             <xs:enumeration value="CtrlShiftL"/>
             <xs:enumeration value="CtrlShiftM"/>
             <xs:enumeration value="CtrlShiftN"/>
             <xs:enumeration value="CtrlShiftO"/>
             <xs:enumeration value="CtrlShiftP"/>
             <xs:enumeration value="CtrlShiftQ"/>
             <xs:enumeration value="CtrlShiftR"/>
             <xs:enumeration value="CtrlShiftS"/>
             <xs:enumeration value="CtrlShiftT"/>
             <xs:enumeration value="CtrlShiftU"/>
             <xs:enumeration value="CtrlShiftV"/>
             <xs:enumeration value="CtrlShiftW"/>
             <xs:enumeration value="CtrlShiftX"/>
             <xs:enumeration value="CtrlShiftY"/>
             <xs:enumeration value="CtrlShiftZ"/>
             <xs:enumeration value="ShiftIns"/>
             <xs:enumeration value="ShiftF1"/>
             <xs:enumeration value="ShiftF2"/>
             <xs:enumeration value="ShiftF3"/>
             <xs:enumeration value="ShiftF4"/>
             <xs:enumeration value="ShiftF5"/>
             <xs:enumeration value="ShiftF6"/>
             <xs:enumeration value="ShiftF7"/>
             <xs:enumeration value="ShiftF8"/>
             <xs:enumeration value="ShiftF9"/>
             <xs:enumeration value="ShiftF10"/>
             <xs:enumeration value="ShiftF11"/>
             <xs:enumeration value="ShiftF12"/>
             <xs:enumeration value=""/>
           </xs:restriction>
         </xs:simpleType>
       </xs:attribute>
     </xs:complexType>
   </xs:element>
</xs:schema>

3。定义一个类来加载菜单

public class MenuLoad
   {
     PRivate PluginCollection m_plugins = null;
     public MenuBar _menbar = new MenuBar();
     public ToolStrip _toolbar = new ToolStrip();
     private OutlookBar bar = new OutlookBar();
     private ImageList imglist = new ImageList();
     private StringBuilder builder = new StringBuilder();

   public MenuLoad()
     {
       bar = _menbar.outlookBar;
     }

   private TabControl tabCtrl;
     public TabControl TabCtrl
     {
       set
       {
         tabCtrl = value;
       }
     }

   private void ValidationEventHandler(object sender, ValidationEventArgs e)
     {
       builder.AppendLine("验证XML文档的时候发生错误:");
       builder.AppendLine("严重级别:" + e.Severity);
       builder.AppendLine("错误信息:" + e.Message);
       builder.AppendLine("------+--------+-------+------+--------+-------+------+--------+-------+");
       builder.AppendLine();
     }

   /**//// <summary>
     /// 验证XML文件是否是合乎规范的文件
     /// </summary>
     /// <param name="xmlfile">文件名称</param>
     /// <returns>是则返回true,否则返回false</returns>
     private bool ValidateXml(string xmlfile)
     {
       bool validXml = false;
       string spath = "";

     spath = application.StartupPath + "\\configurations\\XMLSMenu.xsd";
       if(!System.IO.File.Exists(spath))
       {
         throw new System.IO.FileNotFoundException(String.Format(Resources.StringFileNotFound, spath));
       }

     XmlReaderSettings settings = new XmlReaderSettings();
       XmlSchemaSet schemaSet = new XmlSchemaSet();
       schemaSet.Add(null, spath);
       settings.Schemas.Add(schemaSet);
       settings.ValidationType = ValidationType.Schema;
       settings.ValidationEventHandler += new ValidationEventHandler(ValidationEventHandler);
       settings.ValidationFlags = settings.ValidationFlags | XmlSchemaValidationFlags.ReportValidationWarnings;

     XmlReader reader = XmlReader.Create(xmlfile, settings);


       while(reader.Read())
       {

     }
      
       if(builder.Length > 0)
       {
         validXml = false;
       }
       else
       {
         validXml = true;
       }
       reader.Close();
       return validXml;

   }
     /**//// <summary>
     /// 加载菜单
     /// </summary>
     /// <param name="main">主菜单</param>
     /// <param name="xmlfile">菜单定义文件</param>
     public MainMenu LoadMenus(string xmlfile)
     {
       MainMenu mainmenu = new MainMenu();
      
       try
       {
         using(new WaitCursor())
         {
           //验证XML是否是合乎规范的XML文件
           if(ValidateXml(xmlfile))
           {
             XmlDocument document = new XmlDocument();
             document.Load(xmlfile);

           XmlNode rootNode = document.DocumentElement;
             mainmenu = GetMenus(rootNode); 
           }
           else
           {
             throw new Exception(builder.ToString());
           }
         }
       }
       catch (System.IO.FileNotFoundException)
       {
         Utility.ShowErrorMsg(String.Format(Resources.StringFileNotFound, xmlfile));
       }

     return mainmenu;
     }

   /**//// <summary>
     /// 加载菜单
     /// </summary>
     /// <param name="main">主菜单</param>
     /// <param name="node">菜单项节点</param>
     private MainMenu GetMenus(XmlNode node)
     {
       MainMenu mainmenu = new MainMenu();
       List<XmlNode> nodelist= new List<XmlNode>();
       List<OfficeMenuItem> mnulist = new List<OfficeMenuItem>();
       List<IconPanel> iplist = new List<IconPanel>();
       string menutext ="";
       //首先加载主菜单,避免迭代的时候菜单显示的过分延迟。
       foreach(XmlNode child in node.ChildNodes)
       {
         if(child.NodeType == XmlNodeType.Element && child.Name == "MenuItem")
         {
           menutext = child.Attributes["Name"].Value;
           OfficeMenuItem item = new OfficeMenuItem(true,menutext);
           mainmenu.MenuItems.Add(item);
           IconPanel cp = new IconPanel();
           bar.AddBand(menutext, cp);
           nodelist.Add(child);
           mnulist.Add(item);
           iplist.Add(cp);
         }
       }
       //加载所有的子菜单
       GetSubMenus(iplist.ToArray(),mnulist.ToArray(), nodelist.ToArray());
       return mainmenu;
     }

   /**//// <summary>
     /// 加载所有子菜单
     /// </summary>
     /// <param name="main">主菜单集合</param>
     /// <param name="node">菜单节点集合</param>
     private void GetSubMenus(IconPanel[] iplist ,OfficeMenuItem[] main, XmlNode[] node)
     {
       EventHandler handler = new EventHandler(OnPluginClick);
       EventHandler handler1 = new EventHandler(OnIconClick);
       EventHandler handler2 = new EventHandler(OnButtonClick);
       string asmname;
       string formtag;
       string text;
       MenuClass mc;
       XmlNode child;
       string iconpath = "";
       string iconname = "";
       string msc = "";
       for(int i = 0; i <= main.GetUpperBound(0); i++)
       {
         //foreach(XmlNode child in node[i].ChildNodes)
         for(int j = 0; j < node[i].ChildNodes.Count;j++ )
         {
           child = node[i].ChildNodes[j];
           if(child.NodeType == XmlNodeType.Element && child.Name == "MenuItem")
           {
             asmname = child.Attributes["AssemblyName"].Value;
             formtag = child.Attributes["FormTag"].Value;
             text = child.Attributes["Name"].Value;
             msc = child.Attributes["ShortCut"].Value;
             OfficeMenuItem item = new OfficeMenuItem(true, text, handler);
             iconname = child.Attributes["Image"].Value;
             if(iconname != string.Empty)
             {
               iconpath = Themes.GetCurrentThemePath() +iconname;
               item.IconPath = iconpath;
              
             }
             mc = new MenuClass();
             mc.Assemblyname = asmname;
             mc.FormTag = formtag;

           item.Tag = mc;

           if(msc != string.Empty)
             {
               item.Shortcut = MenuShortCut.GetShortCut(msc);
             }

           main[i].MenuItems.Add(item);

           if((iconpath != string.Empty) && System.IO.File.Exists(iconpath))
             {   //添加按钮到OutlookBar            
               PanelIcon picon = iplist[i].AddIcon(item.Text,Image.FromFile(iconpath),handler1);
               picon.Tag = mc;
               //添加按钮到toolbar
               ToolStripButton button = new ToolStripButton(item.Text, Image.FromFile(iconpath), handler2);
               button.DisplayStyle = ToolStripItemDisplayStyle.Image;
               button.ToolTipText = item.Text;
               button.Tag = mc;
               button.Visible = true;
               _toolbar.Items.Add(button);
             }

           iconpath = "";
             mc = null;

           if(child.ChildNodes.Count > 0)
             {
               GetChildMenu(iplist[i],item, child);
             }
           }
         }
         //添加分割线
         ToolStripSeparator ss = new ToolStripSeparator();
         _toolbar.Items.Add(ss);
       }
     }

   /**//// <summary>
     /// 加载子菜单
     /// </summary>
     /// <param name="parent">父菜单</param>
     /// <param name="node">父菜单定义XML节点</param>
     private void GetChildMenu(IconPanel ip,OfficeMenuItem parent, XmlNode node)
     {
       EventHandler handler = new EventHandler(OnPluginClick);
       EventHandler handler1 = new EventHandler(OnIconClick);
       EventHandler handler2 = new EventHandler(OnButtonClick);

     MenuClass mc;
       string asmname;
       string formtag;
       string text;
       XmlNode child1;
       string iconpath = "";
       string iconname = "";
       string msc = "";
       //foreach(XmlNode child1 in node.ChildNodes)
       for(int i = 0; i < node.ChildNodes.Count - 1;i++ )
       {
         child1 = node.ChildNodes[i];
         //检查是否提供了类型
         asmname = child1.Attributes["AssemblyName"].Value;
         formtag = child1.Attributes["FormTag"].Value;
         text = child1.Attributes["Name"].Value;
         OfficeMenuItem childitem;

       childitem = new OfficeMenuItem(true, text, handler);
         childitem.Name = text;
         mc = new MenuClass();
         mc.Assemblyname = asmname;
         mc.FormTag = formtag;
        
         childitem.Tag = mc;
         //添加快捷键
         msc = child1.Attributes["ShortCut"].Value;
         if(msc != string.Empty)
         {
           childitem.Shortcut = MenuShortCut.GetShortCut(msc);
         }
         //添加图标
         iconname = child1.Attributes["Image"].Value;
         if(iconname != string.Empty)
         {
           iconpath = Themes.GetCurrentThemePath() + iconname;
           childitem.IconPath = iconpath;
         }

       parent.MenuItems.Add(childitem);

       if((iconpath != string.Empty) && System.IO.File.Exists(iconpath))
         {   //添加按钮到OutlookBar            
           PanelIcon picon = ip.AddIcon(childitem.Text, Image.FromFile(iconpath), handler1);
           picon.Tag = mc;
           //添加按钮到toolbar
           ToolStripButton button = new ToolStripButton(childitem.Text, Image.FromFile(iconpath), handler2);
           button.DisplayStyle = ToolStripItemDisplayStyle.Image;
           button.ToolTipText = childitem.Text;
           button.Tag = mc;
           button.Visible = true;
           _toolbar.Items.Add(button);
         }

       iconpath = "";
         mc = null;

       if(child1.ChildNodes.Count > 0)
         {
           GetChildMenu(ip,childitem, child1);
         }
       }
     }

   /**//// <summary>
     /// 打开一个窗体
     /// </summary>
     /// <param name="asmname">窗体类程序集和窗体类的组合,从节点的AssemblyName属性获取</param>
     private  void OpenForm(MenuClass mc)
     {
       string asmname = mc.Assemblyname;
       string formtag = mc.FormTag;

     if (formtag == "")
       {
         throw new Exception(Resources.StringNoFormFlag);
       }

     if(formtag.ToUpper() == "TRUE")
       {
         if(asmname == string.Empty)
         {
           throw new NullReferenceException(Resources.StringAssemblyNull);
         }


         //string[] a = asmname.Split(',');
         object obj = null;
         Type tp = Type.GetType(asmname);
         if(tp != null)
         {
           obj = Activator.CreateInstance(tp);
         }
         else
         {
           throw new Exception("加载程序的时候出错,请检查程序(dll,exe)是否存在或者类型是否正确。");
         }


         //检查是否是Form类
         if((obj == null) | !(obj is Form))
         {
           throw new Exception(Resources.StringNotForm);
         }

       Form frm = (obj as Form);

       //检查打开的第一个窗口是否是MDIFORM
         if(Application.OpenForms[0].IsMdiContainer)
         {
           //作为MDICHILDFORM
           frm.MdiParent = Application.OpenForms[0];
         }
         //加载窗体
         frm.Show();


       }
     }

   /**//// <summary>
     /// 菜单单击事件
     /// </summary>
     /// <param name="sender"></param>
     /// <param name="args"></param>
     private void OnPluginClick(object sender, EventArgs args)
     {
       OfficeMenuItem item = (OfficeMenuItem)sender;
       MenuClass mc = (MenuClass) item.Tag;
       if ((item.Text == "退出") | (item.Text == "EXIT"))
       {
         OnExitClick(sender, args);
         return;
       }
       OpenForm(mc);
     }

   }
这里面用到了delegate,最重要的函数是加载菜单的函数和OnPluginClick函数。

使用这个框架可以动态增加任意的层次的模块。

微软的CAB 使用Resigster site方式来增加模块,感觉不是很方便。

如果您对这个框架感兴趣可以邮件 piyanrong@Gmail.com。

Tags:一个 简单 基于

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接