Build From XML file?

Sep 27, 2009 at 7:46 PM

How would I build a menu dynamically from an XML file?

 

thanks.

Coordinator
Sep 29, 2009 at 7:52 AM

Hi, I think the best way to achieve that is to use XML Serialization/Deserialization.

You can create your own entity class and save their collection as an xml file, then you can get this object by deserialization.

But if you don't want this, you can create your own xml format and rules to change xml to object. The only two things you should provide to the Menu control is an IEnumerable instance as ItemsSource and a HierarchicalDataTemplate object as DataTemplate.

Regards!

Oct 17, 2009 at 10:28 PM
Edited Oct 17, 2009 at 10:41 PM

I was able to build the menu from XAML on the fly; Same can be done with XML as well.  Here is what I did, and the parts to make this work. I used the sample project that comes with the source code download. There are 4 steps explained here.

1. Add new file to the project - text file type. After you add it, change the extention to .xaml.  Mark the file Build Action to Content - not page as is default. In the file add the xaml from the Menu declaration as you want it. I just copied parts of the one that is in the demo, as Menu 1. Copied the full xaml, and added the xmlns in the declaration on line 1.

NOTE: I put the file in a folder /xaml and also have folder /img/ where I have images, marked as Content and use them on the menu.

<menu:Menu

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:menu="clr-namespace:System.Windows.Controls;assembly=Menu">

    <menu:MenuItem Header="File">

        <menu:MenuItem Header="New">

            <menu:MenuItem Header="Project..." Icon="/img/add16.png"/>

            <menu:MenuItem Header="Web Site..."/>

            <menu:MenuItem Header="File..."/>

            <menu:MenuItem Header="Project From Existing Code..."/>

        </menu:MenuItem>      

    </menu:MenuItem>

    <menu:MenuItem Header="Edit">

        <menu:MenuItem Header="Undo"/>      

        <menu:MenuItem Header="Find and Replace">          

            <menu:MenuItem Header="Find Symbol"/>

        </menu:MenuItem>

    </menu:MenuItem>     

    <menu:MenuItem Header="Help">

        <menu:MenuItem Header="How Do I"/>     

    </menu:MenuItem>

</menu:Menu>

 2. In the MainPage.xaml file add a new container, I added StackPanel. 

<StackPanel x:Name="sp" Grid.Row="1" />

3. Next, I updated the MenuBindingSource as follows:

public class MenuBindingSource : INotifyPropertyChanged

    {

        private Uri source;

        private Menu menu;

 

        public Menu Menu

        {

            get { return menu; }

        }

 

        public Uri Source

        {

            get { return source; }

            set

            {

                source = value;

                CreateMenu();

                OnPropertyChanged("Source");

            }

        }

 

        private void CreateMenu()

        {

            //Load here XAML or XML from local or any other valid Uri

            if (Source == null)

                return;

           

            //NOTE: For this to work, the xaml needs to be marked as Content in the project and not as page!

            using (StreamReader reader = new StreamReader(Application.GetResourceStream(this.Source).Stream))

            {

                string xaml = reader.ReadToEnd();

                menu = XamlReader.Load(xaml) as Menu;

            }

        }

 

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)

        {

            PropertyChangedEventHandler handler = this.PropertyChanged;

            if (handler != null)

                handler(this, new PropertyChangedEventArgs(propertyName));

        }

        #endregion

       

    }

4.  Finally in the MainPage.xaml.cs do this, and that is it.

public MainPage()

        {

            InitializeComponent();           

 

            MenuBindingSource mbs = new MenuBindingSource();

            mbs.Source = new Uri("XAML/AdminMenu.xaml", UriKind.Relative);

            Menu mnuMain = mbs.Menu;

            mnuMain.SelectionChanged += new SelectionChangedEventHandler(mnuMain_SelectionChanged);

            sp.Children.Add(mnuMain);

        }

 

        void mnuMain_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            if (e != null && e.AddedItems != null && e.AddedItems.Count != 0)

            {

                MenuItem item = e.AddedItems[0] as MenuItem;

                if (item != null && item.Header != null)

                {

                    MessageBox.Show(item.Header.ToString(), "MenuOnTheFly From XAML", MessageBoxButton.OK);

                }

            }

        }

 

Oct 29, 2014 at 2:39 AM
You can do this for your menu with data binding to an XML source data / file, which provides hierarchical structure itself.