Click here to Skip to main content
15,891,431 members
Articles / Programming Languages / XML

An XML-Driven Menu Strip

Rate me:
Please Sign up or sign in to vote.
4.71/5 (13 votes)
16 Apr 2007CPOL8 min read 128.1K   2.1K   75  
In this article, I'm going to show how to generate a dynamic MenuStrip (.NET 2.0's replacement of the MainMenu control) using recursion in C#. The MenuStrip will be based on XML data which contains all the details about the generated Menu.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using System.Diagnostics;
using System.Xml;

namespace MainMenuEnhanced
{
    public partial class MenuStripEnhanced : MenuStrip
    {
        public MenuStripEnhanced()
        {
            InitializeComponent();
        }

        private string m_xmlPath;
        [ToolboxItem("Extended"), Category("Extended"), Description("The path to the Menu XML configuration file.")]
        public string XmlPath
        {
            get { return m_xmlPath; }
            set     
            {
                if ( m_xmlPath != value )
                {
                    m_xmlPath = value;
                }
            }
        }

        public void LoadDynamicMenu()
        {
            if ( XmlPath != string.Empty )
                LoadDynamicMenu( XmlPath );
        }

        public void LoadDynamicMenu( string xmlPath )
        {
            if ( System.IO.Path.IsPathRooted( XmlPath ) )
                xmlPath = XmlPath;
            else
                xmlPath = System.IO.Path.Combine( Application.StartupPath, XmlPath );

            if ( System.IO.File.Exists( XmlPath ) )
            {
                XmlTextReader reader = new XmlTextReader( xmlPath );
                LoadDynamicMenu( reader );
            }
        }

        public void LoadDynamicMenu( XmlTextReader xmlReader )
        {            
            this.Items.Clear();

            XmlDocument document = new XmlDocument();
            document.Load( xmlReader );

            XmlElement element = document.DocumentElement;

            foreach ( XmlNode node in document.FirstChild.ChildNodes )
            {
                ToolStripMenuItem menuItem = new ToolStripMenuItem();

                menuItem.Name = node.Attributes["Name"].Value;
                menuItem.Text = node.Attributes["Text"].Value;

                this.Items.Add( menuItem );
                GenerateMenusFromXML( node, (ToolStripMenuItem)this.Items[this.Items.Count - 1] );
            }
        }

        private void GenerateMenusFromXML( XmlNode rootNode, ToolStripMenuItem menuItem )
        {
            ToolStripItem item = null;
            ToolStripSeparator separator = null;

            foreach ( XmlNode node in rootNode.ChildNodes )
            {
                if ( node.Attributes["Text"].Value == "-" )
                {
                    separator = new ToolStripSeparator();

                    menuItem.DropDownItems.Add( separator );
                }
                else
                {
                    item = new ToolStripMenuItem();
                    item.Name = node.Attributes["Name"].Value;
                    item.Text = node.Attributes["Text"].Value;

                    menuItem.DropDownItems.Add( item );

                    if ( node.Attributes["FormLocation"] != null )
                        item.Tag = node.Attributes["FormLocation"].Value;

                    // add an event handler to the menu item added
                    if ( node.Attributes["OnClick"] != null )
                    {
                        FindEventsByName( item, this.Parent, true, "MenuItemOn", node.Attributes["OnClick"].Value );
                    }

                    GenerateMenusFromXML( node, (ToolStripMenuItem)menuItem.DropDownItems[menuItem.DropDownItems.Count - 1] );
                }
            }
        }

        private void FindEventsByName( object sender, object receiver, bool bind, string handlerPrefix, string handlerSuffix )
        {
            System.Reflection.EventInfo[] SenderEvent = sender.GetType().GetEvents();
            Type ReceiverType = receiver.GetType();
            System.Reflection.MethodInfo method;

            foreach ( System.Reflection.EventInfo e in SenderEvent )
            {
                method = ReceiverType.GetMethod( string.Format( "{0}{1}{2}", handlerPrefix, e.Name, handlerSuffix ), System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic );

                if ( method != null )
                {

                    System.Delegate d = System.Delegate.CreateDelegate( e.EventHandlerType, receiver, method.Name );

                    if ( bind )
                        e.AddEventHandler( sender, d );
                    else
                        e.RemoveEventHandler( sender, d );
                }
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
I've been working with C# since .NET Beta 1 and have been in the development scene since VB3.

I've always had a passion for development, technology, and computer as a whole. I consider myself one of the lucky few who actually love their job.

I've mostly been involed with web development in the corporate world, but I also work with Windows Forms development at home. Over the past 3 years or so the .NET applications I've developed have been backend maintenance applications. Transfering data, manipulating data, or doing some other back-end processes.

Comments and Discussions