I'd like to override the MenuItem ControlTemplate so that I can customize the mouseover background color of my MenuItems.
I'm using the following xaml:
<Style TargetType="MenuItem">
<Setter Property="Background" Value="#26222b"/>
<Setter Property="Height" Value="25"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Border Padding="10 0 10 0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<ContentPresenter x:Name="ContentPresenter"
Content="{TemplateBinding Header}"
ContentSource="Header"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" Value="#2f2a36"/>
</Trigger>
</Style.Triggers>
</Style>
This does what I expect it to in terms of style, but the buttons no longer respond to click events.
I've also tried using a ControlTemplate.Trigger instead of a Style.Trigger to make the change I want. I don't know which solution is considered proper (please let me know) but neither seemed to address the problem at hand.
It's my understanding that I should be able to override the element's style without having to rewrite its click response functionality, so I assume I'm doing something wrong here to break it.
Just in case it's helpful, below is the xaml in which I've defined the menu itself:
<Menu Grid.Row="0"
Grid.ColumnSpan="2"
IsMainMenu="True">
<Menu.Items>
<MenuItem Header="_File" DataContext="{Binding File}">
<MenuItem Header="_New" Command="{Binding NewCommand}"/>
<MenuItem Header="_Open" Command="{Binding OpenCommand}" />
<MenuItem Header="_Save" Command="{Binding SaveCommand}"/>
<MenuItem Header="_Save as..." Command="{Binding SaveAsCommand}"/>
</MenuItem>
<MenuItem Header="_Format" DataContext="{Binding Editor}">
<MenuItem Header="_Format" Command="{Binding FormatCommand}"/>
<MenuItem Header="_Word wrap" Command="{Binding WrapCommand}"/>
</MenuItem>
<MenuItem Header="_Help" DataContext="{Binding Help}">
<MenuItem Header="_About" Command="{Binding HelpCommand}"/>
</MenuItem>
</Menu.Items>
</Menu>
Any direction would be greatly appreciated. Thanks in advance!
Related
I have in my UI some symbols (that represent electric equipments). I implemented a context menu that allows the user to perform some actions.
I would like to add a non-selectable title label at the top of the context menu;
this item should not be selected or highlighted with the mouse cursor
Like in this image :
How can I do this ??
<UserControl.ContextMenu>
<ContextMenu>
<MenuItem Header="Start" IsEnabled="{Binding ControlPanelViewModel.IsStartEnabled}" Command="{Binding Path=ControlPanelViewModel.StartEscalatorCommand}"/>
<MenuItem Header="Stop" IsEnabled="{Binding ControlPanelViewModel.IsStopEnabled}" Command="{Binding Path=ControlPanelViewModel.StopEscalatorCommand}"/>
<Separator/>
<MenuItem x:Name="OpenControl" Header="Control panel..." Command="{Binding OpenControlPanelCommand}">
<MenuItem.Icon>
<Path Data="M19,4C20.11,4 21,4.9 21,6V18A2,2 0 0,1 19,20H5C3.89,20 3,19.1 3,18V6A2,2 0 0,1 5,4H19M19,18V8H5V18H19Z" Fill="Black" Margin="-5"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</UserControl.ContextMenu>
You can add the title to the ControlTemplate of the ContextMenu. You can get the default ControlTemplate for the ContextMenu using the solution here, and then modify it to add the title. I've done this below:
<UserControl.ContextMenu>
<ContextMenu>
<ContextMenu.Template>
<ControlTemplate TargetType="ContextMenu" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:mwt="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
<mwt:SystemDropShadowChrome Color="#00FFFFFF" Name="Shdw" SnapsToDevicePixels="True">
<Border BorderThickness="{TemplateBinding Border.BorderThickness}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="ContextMenuBorder">
<ScrollViewer Style="{DynamicResource {ComponentResourceKey TypeInTargetAssembly=FrameworkElement, ResourceId=MenuScrollViewer}}" Name="ContextMenuScrollViewer" Margin="1,0,1,0" Grid.ColumnSpan="2">
<StackPanel>
<Label>Your title goes here</Label>
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas Width="0" Height="0" HorizontalAlignment="Left" VerticalAlignment="Top">
<Rectangle Fill="{x:Null}" Name="OpaqueRect" Width="Auto" Height="Auto" />
</Canvas>
<Rectangle RadiusX="2" RadiusY="2" Fill="#FFF1F1F1" Width="28" Margin="1,2,1,2" HorizontalAlignment="Left" />
<Rectangle Fill="#FFE2E3E3" Width="1" Margin="29,2,0,2" HorizontalAlignment="Left" />
<Rectangle Fill="#FFFFFFFF" Width="1" Margin="30,2,0,2" HorizontalAlignment="Left" />
<ItemsPresenter Name="ItemsPresenter" Margin="{TemplateBinding Control.Padding}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" KeyboardNavigation.DirectionalNavigation="Cycle" />
</Grid>
</StackPanel>
</ScrollViewer>
</Border>
</mwt:SystemDropShadowChrome>
<ControlTemplate.Triggers>
<Trigger Property="ContextMenuService.HasDropShadow">
<Setter Property="FrameworkElement.Margin" TargetName="Shdw">
<Setter.Value>
<Thickness>0,0,5,5</Thickness>
</Setter.Value>
</Setter>
<Setter Property="mwt:SystemDropShadowChrome.Color" TargetName="Shdw">
<Setter.Value>
<Color>#71000000</Color>
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>True</s:Boolean>
</Trigger.Value>
</Trigger>
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="ContextMenuScrollViewer">
<Setter Property="Canvas.Top" TargetName="OpaqueRect">
<Setter.Value>
<Binding Path="VerticalOffset" ElementName="ContextMenuScrollViewer" />
</Setter.Value>
</Setter>
<Setter Property="Canvas.Left" TargetName="OpaqueRect">
<Setter.Value>
<Binding Path="HorizontalOffset" ElementName="ContextMenuScrollViewer" />
</Setter.Value>
</Setter>
<Trigger.Value>
<s:Boolean>False</s:Boolean>
</Trigger.Value>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContextMenu.Template>
<MenuItem Header="Start" IsEnabled="{Binding ControlPanelViewModel.IsStartEnabled}" Command="{Binding Path=ControlPanelViewModel.StartEscalatorCommand}"/>
<MenuItem Header="Stop" IsEnabled="{Binding ControlPanelViewModel.IsStopEnabled}" Command="{Binding Path=ControlPanelViewModel.StopEscalatorCommand}"/>
<Separator/>
<MenuItem x:Name="OpenControl" Header="Control panel..." Command="{Binding OpenControlPanelCommand}">
<MenuItem.Icon>
<Path Data="M19,4C20.11,4 21,4.9 21,6V18A2,2 0 0,1 19,20H5C3.89,20 3,19.1 3,18V6A2,2 0 0,1 5,4H19M19,18V8H5V18H19Z" Fill="Black" Margin="-5"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</UserControl.ContextMenu>
The key modification was to wrap the Grid in a StackPanel and add a Label with your title above the Grid. Because the default ControlTemplate uses Aero, you'll need to reference PresentationFramework.Aero in your project.
I am trying to create a context menu which allows the user to see what is under it, and so I have made the Background for both the ContextMenu, and its MenuItems Transparent. When the user moves the mouse over the MenuItems(hovers) they should show up due to a ControlTemplate Trigger on IsHighlighted. The problem is that when the mouse is over the transparent part of the MenuItems the Trigger is not working. If I change the background color of either the ContextMenu, or its MenuItems to something other than Transparent the trigger works. I thought a Transparent Background was supposed to behave like a solid color, but in this case it is not. Any ideas how to make this work?
<Window x:Class="TransparentContextMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="600" Width="800">
<Window.Resources>
<ControlTemplate x:Key="contextMenuItemTemplate" TargetType="{x:Type MenuItem}">
<Grid>
<Polygon Points="0,0 180,0 180,30 0,30" Fill="Transparent" x:Name="Background"/>
<Polygon Points="0,0 180,0 180,30 0,30" Opacity="0" x:Name="HoverBorder" Fill="Gray"/>
<ContentPresenter ContentSource="Header" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter Property="Opacity" Value="1" TargetName="HoverBorder"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="contextMenuStyle" TargetType="{x:Type ContextMenu}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Border Background="Transparent">
<StackPanel IsItemsHost="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="Transparent">
<Grid.ContextMenu>
<ContextMenu Style="{StaticResource contextMenuStyle}">
<MenuItem Header="Item A" Template="{StaticResource contextMenuItemTemplate}"/>
<MenuItem Header="Item B" Template="{StaticResource contextMenuItemTemplate}"/>
<MenuItem Header="Item C" Template="{StaticResource contextMenuItemTemplate}"/>
<MenuItem Header="Item D" Template="{StaticResource contextMenuItemTemplate}"/>
<MenuItem Header="Item E" Template="{StaticResource contextMenuItemTemplate}"/>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
Try setting background to 'null' instead.
I've got next makrup:
<Style TargetType="{x:Type MenuItem}">
<Setter Property="MinWidth" Value="65" />
<Setter Property="MinHeight" Value="30" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="MainBorder" BorderThickness="1" Background="Black">
<TextBlock Margin="5" Text="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" />
<Popup x:Name="SubMenuPopup" IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Right"
AllowsTransparency="True" Focusable="False">
<Border Background="Gray">
<Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True" Background="Transparent">
<StackPanel Margin="0" IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle" Background="Gray" />
</Grid>
</Border>
</Popup>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
When I create MenuItem somewhere and set it's Header property with "_" symbol - it doesn't create shortcut for this menu item.
Example - letter 'F' is not underlined and shortcut doesn't work.
How to support shortcuts in ControlTemplates in MenuItems?
Thanks.
It is not the complete template but instead of the TextBlock put a ContentPresenter that can recognize access keys:
<ContentPresenter Margin="5" Content="{TemplateBinding Header}" TextBlock.Foreground="{TemplateBinding Foreground}" RecognizesAccessKey="True" />
I suppose the xaml you have pasted here is only part of your implementation, so my solution is onl y a continuation of yours with the access key working...
You can find entire templates just like this one: http://msdn.microsoft.com/en-us/library/ms747082%28v=vs.85%29.aspx
If you want you menu item letter to underline itself of keypress then you have to set the InputGesture on menuitem like this:
<MenuItem Header="_File"
InputGestureText="Ctrl+F"
Commmand={Binding NewFileCommand}/>
But if you want to create shortcut for the menuitem command then you will have to create the commandbindings like below on your window:
<Window.CommandBindings>
<CommandBinding Command="local:MyCommands.NewFile" Executed="NewFile_Executed" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="F" Modifiers="Control" Command="local:MyCommands.NewFile"/>
</Window.InputBindings>
I have a project here where I require customizing the context menu in my WPF application in which a button would be placed at the bottom of all the menuitems.
However, if I were to add the button through the XAML, it would appear as another item in the collection in the context menu and the mouse-over highlight would act on it.
I would like to have the context menu tuned to a grid-like style whereby I could customize the style underneath it.
Any idea how I can achieve this (preferably in the XAML)?
It's actually pretty straightforward in the XAML.
Just define it under the element for which you want to have the context menu.
<Border>
<Border.ContextMenu>
<ContextMenu>
<ContextMenu.Template>
<ControlTemplate>
<Grid>
<!--Put anything you want in here.-->
</Grid>
</ControlTemplate>
</ContextMenu.Template>
</ContextMenu>
</Border.ContextMenu>
</Border>
For your menu item style with the button in the item you can use the following code:
Note - Adding items to the Header will keep it in the same MenuItem, but if added to the MenuItem only it will be regarded as a new MenuItem.
<ContextMenu>
<ContextMenu.Items>
<MenuItem>
<MenuItem.Header>
<StackPanel>
<TextBlock Text="Item 1"/>
<Button Content="Button 1" Margin="5"/>
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem>
<MenuItem.Header>
<StackPanel>
<TextBlock Text="Item 2"/>
<Button Content="Button 2" Margin="5"/>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</ContextMenu.Items>
</ContextMenu>
This will be the resulting ContextMenu:
From there you can style the MenuItem or Button etc.
Hope it helps!
You can start with the example style/template (from here) for ContextMenu and adjust it to your needs.
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Grid.IsSharedSizeScope" Value="true" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Border x:Name="Border"
Background="{StaticResource MenuPopupBrush}"
BorderThickness="1">
<Border.BorderBrush>
<SolidColorBrush Color="{StaticResource BorderMediumColor}" />
</Border.BorderBrush>
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Cycle" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" Value="true">
<Setter TargetName="Border" Property="Padding" Value="0,3,0,3" />
<Setter TargetName="Border" Property="CornerRadius" Value="4" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I create popup menu like this.
<DockPanel.ContextMenu>
<ContextMenu Background="#CD252220" Opacity="0.95" Foreground="LightGray" BorderBrush="DarkGray">
<MenuItem Header="_Save Image..." x:Name="btSave" IsEnabled="False" Click="btSave_Click" Style="{StaticResource MyStyle}">
<MenuItem.Icon>
<Image Source="icons/save.png" Width="16" Height="16" Style="{StaticResource IconStyle}"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</DockPanel.ContextMenu>
Why left-side of this menu is WHITE????? It'll be a #CD252220 color or transparent, bun not white!!!!!!
How to fix it? :)
http://itrash.ru/idb/40e872e71346dcf9bd58ba8aec0b2a17/omenu.png.html - menu screenshot
P.S. In XP it's OK. Menu is White only on Vista (don't have W7)
I find solution! You have to just set property OverridesDefaultStyle in Style-defenition section ;)
<Style x:Key="{x:Type ContextMenu}" TargetType="{x:Type ContextMenu}">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Border Background="#CD222120" CornerRadius="7, 7, 8, 8" BorderBrush="DarkGray" BorderThickness="2" Opacity="0.96">
<StackPanel ClipToBounds="True" Orientation="Vertical" IsItemsHost="True" Margin="5,4,5,4"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="{x:Static MenuItem.TopLevelItemTemplateKey}" TargetType="{x:Type MenuItem}">
<Border Name="Border" >
<Grid>
<ContentPresenter Margin="6,3,6,3" ContentSource="Header" RecognizesAccessKey="True" />
</Grid>
</Border>
</ControlTemplate>
If you will declare a custom style for your context menu, This way it will be same for all OS.