Binding menus using HeirarchicalDataTemplates

 

One WPF feature that is not covered a lot is the HeirarchicalDataTemplate and hence, I asked my intern, Ahmad El-Shafey, to try something on this feature. And yeah, he did write a blog post on it :) ... this is his post on his experience with HeirarchicalData templates.

"Some people use DataTemplates and/or HierarchicalDataTemplates to bind MenuItem content to a data source, like this:

<HierarchicalDataTemplate DataType="Menu" ItemsSource="{Binding XPath=*}">

<TextBlock Header="{Binding XPath=@Name}"/>

</HierarchicalDataTemplate>

I wasn’t so comfortable with this because you are creating a TextBlock element inside the items of our MenuItem, and binding its Text property to the data source. What we really want to do is bind the Header element of the MenuItems to the data source, without creating more elements.

What we need to do is create a Style and bind it to our data source, and then set this Style as the ItemContainerStyle of our MenuItem. Let’s say we have XML data that looks like this:

<MenuContent>

  <Category Title="Cat 1">

    <Item Name="Item 1"></Item>

    <Item Name="Item 2"></Item>

  </Category>

  <Category Title="Cat 2">

    <Item Name="Item 1"></Item>

  </Category>

</MenuContent>

So, to display this hierarchical data in a hierarchical menu, first we create a Style for “Item” elements inside the Page’s Resources area and specify a Setter for Header property with the Binding value:

<Style x:Key="ItemStyle">

<Setter Property="MenuItem.Header" Value="{Binding XPath=@Name}"/>

</Style>

Then we create a Style for “Category” elements, also in the Page’s resources area. We have to set more attributes in this Style:

<Style x:Key="CatStyle">

<Setter Property="MenuItem.Header" Value="{Binding XPath=@Title}"/>

<Setter Property="MenuItem.ItemsSource" Value="{Binding XPath=Item}"/>

<Setter Property="MenuItem.ItemContainerStyle" Value="{StaticResource ItemStyle}"/>

</Style>

The ItemsSource property is set to the path of the children, and the ItemContainerStyle property—which specifies the style of the sub MenuItems—is set to the first Style we created.

Then in the Page’s body we create the Menu as follows:

<Menu Height="22" Margin="0,0,100,0" Name="menu1" VerticalAlignment="Top">

<MenuItem Header="Samples"

            ItemsSource="{Binding Source={StaticResource MenuContentXml}, XPath=Category}"

ItemContainerStyle="{StaticResource CatStyle}"

Click="MenuItem_Click"/>

</Menu>

This creates the menu and binds it to our XmlDataProvider object (called MenuContentXML in our code). Please see the complete project attached.

It’s interesting to note that Styles are inherited by children by default. So we can use only one Style to bind the XML data to the MenuItem’s header without regard to how many levels of children exist. But then we have to use same tag name for children at any level and they all must have the same attribute name for the attribute which we will use for binding to the Header. See the other attached project for an example on this."

Both the projects (one using xml data with different tags in the heirarchy and the other with all heirarchical tags being the same) are attached. Hopefully this will help readers in understanding the heirarchicaldata templating better :)

 

Share this post

 

HeirarchicalMenu - xml data.zip