一个简单的基于XML的模块集成框架
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方式来增加模块,感觉不是很方便。
以上就是一个简单的基于XML的模块集成框架的内容,更多相关内容请关注硕下网()!