TheoFontane - Di 29.03.11 17:28
Titel: MenuStrip dynamisch aus beliebig geschachteltem XML aufbauen
Hallo,
ich möchte mein MenuStrip-Element dynamisch zur Laufzeit aus einer XML-Datei laden, die beliebig tief geschachtelt ist. Aktuell werden die Elemente im MenuStrip zwar hierarchisch, dafür aber (teilweise falsch geschachtelt) ca. viermal angelegt - ich muss noch einen Denkfehler in der Rekursion haben...
Hier meine zwei Funktionen, wie sie bisher aussehen:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62:
| public static bool retrieveMenuStrip(ref MenuStrip menuStrip) { try { if (menuStrip == null) return false; menuStrip.Items.Clear(); XDocument xDoc = XDocument.Load(menueListConfigurationFile); XName b = standardXMLNameSpace + "Menu"; var menuQuery = from menuItem in xDoc.Element(b).DescendantsAndSelf() select menuItem; if (menuQuery.Count().Equals(0)) throw new Exception("Menu is not defined. Please check the definition file."); ToolStripMenuItem newItem = new ToolStripMenuItem("DUMMY"); if (!getMenuStructure(menuQuery.ElementAt(0), ref newItem)) return false; menuStrip.Items.Add(newItem);
return true; } catch (Exception ex) { throw new Exception("retrieveMenuStrip", ex); } }
private static bool getMenuStructure(XElement menuElement, ref ToolStripMenuItem menuStripItem) { try { foreach (XElement subElement in menuElement.Descendants()) { ToolStripMenuItem newStripItem = new ToolStripMenuItem(); if (subElement.Name.LocalName.Equals("MenuElement")) { newStripItem.Name = subElement.Attribute("MenuName").Value; newStripItem.Tag = "SUBMENU"; newStripItem.Text = subElement.Name.LocalName; if (!getMenuStructure(subElement, ref newStripItem)) return false; } else if (subElement.Name.LocalName.Equals("Form")) { newStripItem.Name = subElement.Attribute("FormName").Value; newStripItem.DisplayStyle = ToolStripItemDisplayStyle.Text; newStripItem.Tag = "FORM"; newStripItem.Text = subElement.Attribute("Title").Value; } else { continue; } menuStripItem.DropDown.Items.Add(newStripItem); } return true; } catch (Exception ex) { throw new Exception("getMenuStructure", ex); } } |
Nur der Vollständigkeit halber hier auch die zugehörige XML-Datei. Zur Erklärung: Ein "MenuElement" besitzt immer ein anderes "MenuElement" als Kind oder ein "Form"-Element.
XML-Daten
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| <?xml version="1.0" encoding="utf-8" ?> <Menu> <MenuElement MenuName="Start"> <Form FormName="TracesForm" Title="Traces"/> <MenuElement MenuName="SubMenue1"> <MenuElement MenuName="SubSubMenue1"> <Form FormName="AlarmsForm" Title="Alarms"/> </MenuElement> <MenuElement MenuName="SubSubMenue2"></MenuElement> </MenuElement> <MenuElement MenuName="Edit"> <MenuElement MenuName="First"> </MenuElement> <MenuElement MenuName="Second"> </MenuElement> <MenuElement MenuName="Third"> <Form FormName="TestForm" Title="Test 1"/> <Form FormName="TestGridForm" Title="Grid 1"/> <Form FormName="TestGridForm" Title="Grid 2"/> </MenuElement> </MenuElement> </MenuItem> </Menu> |
Fällt einem von euch auf, was ich in der Rekursion falsch gemacht haben könnte?
Danke im Voraus für alle Hinweise und Ideen!
Theo
TheoFontane - Mi 30.03.11 11:18
Für den Fall das jemand dieses Forum und diesen Thread in einer Suchmaschine finden sollte: Ich habe einen guten Lösungsansatz gefunden und auf mein Problem adaptieren könnten.
Quelle des Lösungsansatzes:
http://seattlesoftware.wordpress.com/2009/03/16/recursively-processing-xml-elements-in-c/#comment-166
Hier der überarbeitete Code für die rekursive Funktion.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| private static void getMenuStructure(XElement menuElement, ref ToolStripMenuItem menuStripItem) { try { if (!menuElement.HasElements) { if (menuElement.Name.LocalName.Equals("Form")) { addFormItemToMenuStripItem(menuElement, menuStripItem); } else if (menuElement.Name.LocalName.Equals("MenuElement")) { addMenuItemToMenuStripItem(menuElement, menuStripItem); } } else { ToolStripMenuItem newStripItem = addMenuItemToMenuStripItem(menuElement, menuStripItem); foreach (XElement subElement in menuElement.Elements()) { getMenuStructure(subElement, ref newStripItem); } } } catch (Exception ex) { throw new Exception("getMenuStructure", ex); } }
private static ToolStripMenuItem addFormItemToMenuStripItem(XElement menuElement, ToolStripMenuItem menuStripItem) { ToolStripMenuItem newStripItem = new ToolStripMenuItem(); newStripItem.Name = menuElement.Attribute("FormName").Value; newStripItem.DisplayStyle = ToolStripItemDisplayStyle.Text; newStripItem.Tag = "FORM"; newStripItem.Text = menuElement.Attribute("Title").Value; menuStripItem.DropDown.Items.Add(newStripItem); return newStripItem; }
private static ToolStripMenuItem addMenuItemToMenuStripItem(XElement menuElement, ToolStripMenuItem menuStripItem) { ToolStripMenuItem newStripItem = new ToolStripMenuItem(); newStripItem.Name = menuElement.Attribute("MenuName").Value; newStripItem.Tag = "SUBMENU"; newStripItem.Text = newStripItem.Name; menuStripItem.DropDown.Items.Add(newStripItem); return newStripItem; } |
Vielen Dank für die rege Beteiligung - ich werde mal nach einem anderen Forum Ausschau halten...