treehouse
treehouse

Reputation: 2531

WPF MenuItem Header and HeaderTemplate

I want to bind a list of KeyValuePair to a list of MenuItems. I thought I should use MenuIten.HeaderTemplate, but it didn't work. I only got blank headers.

            <MenuItem 
                Header="Template" 
                ItemsSource="{Binding Path=Samples}">
                <MenuItem.ItemTemplate>
                    <DataTemplate>
                        <MenuItem>
                            <MenuItem.HeaderTemplate>
                                <DataTemplate>
                                    <StackPanel Orientation="Horizontal">
                                        <TextBlock Text="{Binding Path=Key}" FontWeight="Bold"/>
                                        <TextBlock Text="{Binding Path=Value}" FontStyle="Italic" Margin="5,0,0,0"/>
                                    </StackPanel>
                                </DataTemplate>
                            </MenuItem.HeaderTemplate>                            </MenuItem>
                    </DataTemplate>
                </MenuItem.ItemTemplate>
            </MenuItem>

Then I replaced MenuItem.HeaderTemplate with MenuItem.Header, it worked.

            <MenuItem 
                Header="Template" 
                ItemsSource="{Binding Path=Samples}">
                <MenuItem.ItemTemplate>
                    <DataTemplate>
                        <MenuItem>
                            <MenuItem.Header>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Path=Key}" FontWeight="Bold"/>
                                    <TextBlock Text="{Binding Path=Value}" FontStyle="Italic" Margin="2,0,0,0"/>
                                </StackPanel>
                            </MenuItem.Header>
                        </MenuItem>
                    </DataTemplate>
                </MenuItem.ItemTemplate>
            </MenuItem>

Can anyone explain to me why HeaderTemplate doesn't work here?

Upvotes: 9

Views: 32439

Answers (4)

Artur A
Artur A

Reputation: 9129

The purpose of the Template is to add some elements to the VisualTree. DataTemplate is used for the sub-items ([Sub]MenuItem, ListBoxItem in ListBox, and so on) and is applied to the items holder, it is contrary to the ControlTemplate, wich is applied to the control itself. What you actually did by this

<MenuItem 
            Header="Template" 
            ItemsSource="{Binding Path=Samples}">
            <MenuItem.ItemTemplate>
                <DataTemplate>
                       ....
   </DataTemplate>
  </MenuItem.ItemTemplate>
</MenuItem>

is telling "I want take MenuItem content and Insert the data, wich must be visualized". And then insert this insted dots:

 <MenuItem Header="{Binding}">... </MenuItem>

So you are inserting additional menu item to the currently iterating menu item. I can't see the point. Next is more clear:

 <MenuItem Header="Template" ItemsSource="{Binding Samples}">
         <MenuItem.Resources>
            <Style TargetType="{x:Type MenuItem}">
               <Setter Property="Command" Value="{Binding SomeCommand}" />
            </Style>            
        </MenuItem.Resources>
       <MenuItem.ItemTemplate>
          <DataTemplate>
              <TextBlock Text="{Binding Name}" />
          </DataTemplate>             
       </MenuItem.ItemTemplate>
    </MenuItem>

Upvotes: 1

treehouse
treehouse

Reputation: 2531

Micah is correct. In the first approach I told the menu item how to template itself but never told it what data it binds to! The following works:

            <MenuItem 
            Header="Template" 
            ItemsSource="{Binding Path=Samples}">
            <MenuItem.ItemTemplate>
                <DataTemplate>
                    <MenuItem Header="{Binding}">
                        <MenuItem.HeaderTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Text="{Binding Path=Key}" FontWeight="Bold"/>
                                    <TextBlock Text="{Binding Path=Value}" FontStyle="Italic" Margin="5,0,0,0"/>
                                </StackPanel>
                            </DataTemplate>
                        </MenuItem.HeaderTemplate>
                     </MenuItem>
                </DataTemplate>
            </MenuItem.ItemTemplate>
        </MenuItem>

Upvotes: 15

Thomas Levesque
Thomas Levesque

Reputation: 292405

The HeaderTemplate definition should be a DataTemplate, not direct UI content :

...
<MenuItem.HeaderTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=Key}" FontWeight="Bold"/>
            <TextBlock Text="{Binding Path=Value}" FontStyle="Italic" Margin="2,0,0,0"/>
        </StackPanel>
    </DataTemplate>
</MenuItem.HeaderTemplate>
...

Upvotes: 0

Micah
Micah

Reputation: 116060

Because the HeaderTemplate doesn't have access to the data being bound to the menu item.

Upvotes: 9

Related Questions