Reputation: 551
I had a WPF menu which I'd styled using control templates. Then the client wanted to use images instead of text for the Top Level navigation items.
No problem, I created a control template for each top-level item and set my Template attribute on each MenuItem to match the custom template like the one below. I've a Trigger that changes the image on rollover.
My problem is that when you click on the Menu Item that should have a sub-menu items that they no longer drop-down.
The commands fire for the Top-level items that don't have children. And as soon as I remove my code specifying the template from my Menu Item with children I see the text version with the drop-down.
What do I need to do to keep my image-based top-level menu item and keep my drop-downs?
Thanks in advance.
<Menu Grid.Row="0" Grid.Column="0" Name="uxMenu" Margin="0 2 0 0">
<MenuItem Header="Home" Name="uxHome" Command="cmds:NavigationCommands.HomeViewNavigationCommand" Template="{DynamicResource HomeButtonTemplate}"/>
<MenuItem Header="Admin" Name="uxAdmin" Template="{DynamicResource MenuExitButtonTemplate}">
<MenuItem Header="_Setup">
<MenuItem Header="_Overview" Command="cmds:NavigationCommands.MenuAdminSetupOverviewNavigationCommand"/>
<MenuItem Header="_Cameras" Command="cmds:NavigationCommands.MenuAdminSetupCameraNavigationCommand" />
</MenuItem>
</MenuItem>
</Menu>
<ControlTemplate x:Key="HomeButtonTemplate" TargetType="{x:Type MenuItem}">
<Grid >
<Image x:Name="myimage" Source="/Images/Navigation/home_off.png" Width="100" Height="52" />
</Grid>
<ControlTemplate.Triggers >
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter TargetName="myimage" Property="Source" Value="/Images/Navigation/home_on.png" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
In response to H.B's post...
I do have a big ol' set of control templates that I'm currently using to style my menu. So if I want to specify a different control template for each of my top level headers I'm going to have to have an entirely new set of control templates for each one?
I'm unsure of the exact syntax to use, especially for the x:Key and TargetType attributes.
For example. My current code looks like this for my TopLevelHeader and SubmenuHeader control templates. (Copied from the 'menutemplatingpage' you reference')
<!-- TopLevelHeader (children)-->
<ControlTemplate x:Key="{x:Static MenuItem.TopLevelHeaderTemplateKey}" TargetType="MenuItem">
<Border Name="Border">
<Grid>
<ContentPresenter Margin="0 24 0 14" ContentSource="Header" RecognizesAccessKey="True" />
<Popup
Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border
Name="SubmenuBorder"
SnapsToDevicePixels="True"
Background="{StaticResource WindowBackgroundBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1" >
<StackPanel
IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="true">
<Setter TargetName="Popup" Property="PopupAnimation" Value="None"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="false">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter TargetName="Border" Property="Background" Value="Transparent"/>
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent"/>
<Setter TargetName="Border" Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="#fff"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter TargetName="Border" Property="Background" Value="Transparent"/>
<Setter TargetName="Border" Property="BorderBrush" Value="Transparent"/>
<Setter TargetName="Border" Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="True">
<Setter TargetName="SubmenuBorder" Property="CornerRadius" Value="0,0,4,4"/>
<Setter TargetName="SubmenuBorder" Property="Padding" Value="10"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- SubmenuHeader -->
<ControlTemplate x:Key="{x:Static MenuItem.SubmenuHeaderTemplateKey}" TargetType="MenuItem">
<Border Name="Border" >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Icon"/>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" SharedSizeGroup="Shortcut"/>
<ColumnDefinition Width="13"/>
</Grid.ColumnDefinitions>
<ContentPresenter
Name="Icon"
Margin="6,0,6,0"
VerticalAlignment="Center"
ContentSource="Icon"/>
<ContentPresenter
Name="HeaderHost"
Grid.Column="1"
ContentSource="Header"
RecognizesAccessKey="True"/>
<TextBlock x:Name="InputGestureText"
Grid.Column="2"
Text="{TemplateBinding InputGestureText}"
Margin="5,2,2,2"
DockPanel.Dock="Right"/>
<Path
Grid.Column="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 0 7 L 4 3.5 Z"
Fill="{StaticResource GlyphBrush}" />
<Popup
Name="Popup"
Placement="Right"
HorizontalOffset="-4"
IsOpen="{TemplateBinding IsSubmenuOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Fade">
<Border
Name="SubmenuBorder"
SnapsToDevicePixels="True"
Background="{StaticResource WindowBackgroundBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1" >
<StackPanel
IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="Border" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/>
</Trigger>
<Trigger SourceName="Popup" Property="Popup.AllowsTransparency" Value="True">
<Setter TargetName="SubmenuBorder" Property="CornerRadius" Value="4"/>
<Setter TargetName="SubmenuBorder" Property="Padding" Value="0,3,0,3"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
So if I add my new Control template with the key of "HomeButtonTemplate" as shown near the top of my post I'm going to have to add a new section (as well as all the other ControlTemplates for things like SubmenuItem etc.
How do these new ControlTemplates know that they belong to the same group of control templates? I feel I'm not asking this correctly.
Thanks for any advice you can give.
Upvotes: 4
Views: 5192
Reputation: 594
This might be a bit late but I recently had the same issue. What worked for me was to create a StackPanel like so
<StackPanel ClipToBounds="True"
Orientation="Horizontal"
IsItemsHost="True" />
inside the Border
which is inside the ControlTemplate
.
Leaving you with something along the lines of this.
<ControlTemplate TargetType="Menu">
<Border Background="{TemplateBinding Background}"
BorderBrush="#252525"
BorderThickness="1"
CornerRadius="5">
<StackPanel ClipToBounds="True"
Orientation="Horizontal"
IsItemsHost="True" />
</Border>
</ControlTemplate>
Upvotes: 1
Reputation: 184441
You completely remove the existing template (which is fairly complex) by specifying your own, your template no longer provides the necessary functionality. There is a part in the control template indentified with the name PART_Popup
, which is used to display sub-items.
Check this page for a link (Default WPF themes
) where you can download the default styles which include the templates to see what your template should look like.
Also have a look at the menu templating page which should give you an idea just how complex templating the menu is.
Upvotes: 6