I want to have a dropdown menu with custom background color of the menu item. I was able to achieve this with the help of this answer. The root menu item in my GUI has only an icon with no Header. The code I used to define the menu item icon is as follows:
<Style x:Key="MenuIcon" TargetType="{x:Type MenuItem}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Menu Background="Orange">
<MenuItem ToolTip="Menu" BorderBrush="White">
<MenuItem.Header>
<StackPanel
Width="60"
Height="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Orange"
Orientation="Horizontal">
<Viewbox
Margin="9"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Fill">
<Grid Margin="-8,0,0,0">
<Path
x:Name="MenuIconFillStyle"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M6 36v-3h36v3Zm0-10.5v-3h36v3ZM615v-3h36v3Z"
Fill="White" />
</Grid>
</Viewbox>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="MenuIconFillStyle" Property="Fill" Value="Yellow" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I added the following in the <ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}"> taken from here:
<ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
and the following in the ControlTemplate.Triggers:
<Trigger Property="Icon" Value="True">
<Setter Property="Visibility" TargetName="Icon" Value="Visible"/>
</Trigger>
The Template="{DynamicResource MenuItemControlTemplate1}" is as follows:
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot"
BorderBrush="#535353"
CornerRadius="3"
BorderThickness="1"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Width="26" Height="16" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" />
<ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="1" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom" HorizontalOffset="-2">
<Border x:Name="SubMenuBorder" BorderBrush="#595959" BorderThickness="1" Background="#3A3A3A" Padding="2">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=SubMenuBorder}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="True">
<Setter Property="Visibility" TargetName="Icon" Value="Visible"/>
</Trigger>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="{StaticResource DarkBrush}"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#2C2C2C"/>
<Setter Property="BorderThickness" TargetName="templateRoot" Value="1"></Setter>
</Trigger>
<Trigger Property="CanContentScroll" SourceName="SubMenuScrollViewer" Value="False">
<Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}"/>
<Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}"/>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource Clicked}" />
<Setter Property="Header" Value="Test" />
<Setter Property="BorderBrush" Value="#2C2C2C"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
The custom background and the icon for the MenuItem is specified as in the following code snippet:
<Grid Background="#535353">
<Menu Width="100" Height="22" Margin="10, 10, 5, 5" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top">
<MenuItem Style="{StaticResource MenuIcon}" Template="{DynamicResource MenuItemControlTemplate1}">
</Menu>
</Grid>
The icon defined in Style is not rendering in the MenuItem along with the Template (Template="{DynamicResource MenuItemControlTemplate1}") used for setting the background color. How can this be achieved?
Edit
Based on the suggestion of #mm8, I tried to combine the Styles that are responsible for changing the background color (The Style with x:Key="TopLevelHeaderStyle" which is borrowed from here) and inserting a menu item icon in the root menu and came up with the following:
<Style x:Key="TopLevelHeaderStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Background" Value="#000d18"/>
<Setter Property="Foreground" Value="#d8d8d8"/>
<Setter Property="Width" Value="72"/>
<Setter Property="Height" Value="42"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Border x:Name="MenuItemBorder" Width="72" Height="42" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Header}" ContentSource="Header" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Popup AllowsTransparency="True" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PlacementTarget="{Binding ElementName=MenuItemBorder}"
HorizontalOffset="1" VerticalOffset="-1">
<Border BorderBrush="#414141" Background="#414141">
<ScrollViewer Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" Value="#1271C8"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--MenuIcon-->
<Style x:Key="MenuIcon" TargetType="{x:Type MenuItem}" BasedOn="{StaticResource TopLevelHeaderStyle}">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Menu>
<MenuItem>
<MenuItem.Header>
<StackPanel
Width="60"
Height="50"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="Orange"
Orientation="Horizontal">
<Viewbox
Margin="9"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Fill">
<Grid Margin="-8,0,0,0">
<Path x:Name="MenuIconFillStyle"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="White"
Data="M6 36v-3h36v3Zm0-10.5v-3h36v3ZM6 15v-3h36v3Z"
/>
</Grid>
</Viewbox>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
And used it as follows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Menu Grid.Column="0" FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Top">
<MenuItem Header="File" Style="{StaticResource TopLevelHeaderStyle}">
<MenuItem Header="New"/>
<MenuItem Header="Open"/>
<MenuItem Header="Close"/>
</MenuItem>
</Menu>
<Menu Grid.Column="1" FontSize="24" HorizontalAlignment="Left" VerticalAlignment="Top">
<MenuItem Margin="-11, 0,0,0" Width="50" Header="File" Style="{StaticResource MenuIcon}">
<MenuItem Header="New1"/>
<MenuItem Header="Open1"/>
<MenuItem Header="Close1"/>
</MenuItem>
</Menu>
</Grid>
Now the drop down menu having an icon in the root menu item is not showing the other menu item contents New1, Open1 and Close1 What mistake am I making?
The MenuItem control has a DependencyProperty of type Object named 'Icon'. This property is reserved for your exact purpose.
First you need to bind the Data in the Path within your MenuItem ControlTemplate to the Icon property of the parent MenuItem. Like this:
<Path x:Name="MenuIconFillStyle"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="{TemplateBinding Icon}"
Fill="White" />
Now you may specify a PathGeometry in XAML like this. Its contents will be your SVG data:
<PathGeometry x:Key="MySpecialPath">M2 0C0.89687</PathGeometry>
Finally, apply this path using its Key to any MenuItem as a StaticResource:
<Menu Width="100" Height="22" Margin="10, 10, 5, 5" HorizontalAlignment="Left" Background="White" VerticalAlignment="Top">
<MenuItem Template="{DynamicResource MenuItemControlTemplate1}"
Icon="{StaticResource MySpecialPath}">
</Menu>
If you want a bit more control out of your icons (multiple colors, different size, margin, etc..) It is a bit more involved. Just remember that the 'Path' property on MenuItem is an Object so you can hypothetically use any 'Presenting' element (Does not need to be Path) in your MenuItem ControlTemplate and TemplateBind it to MenuItem.Path - then pass any type of 'Presented' object to the MenuItem (does not need to be PathGeometry). You can look into using a
<ContentPresenter Content="{TemplateBinding Icon}" />
instead of the Path control in the MenuItem ControlTemplate - and then giving literally any "Icon" control to your MenuItem.Path property in your XAML.
Related
In the following XAML I need to display the blue rectangle inside menu item with no grey empty area surrounding it. But as shown in the screen below, the rectangle inside menu item is showing lots of empty space surrounding the rectangle. Question: What I may be doing wrong here and how we can get rid of the empty space from the menu item? I've tried the using Margin and StackPanel. But no success so far. I think we probably need some sort of menu item template here. I'm following this WPF tutorial.
XAML:
<Window x:Class="WpfTESTApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTESTApp"
mc:Ignorable="d"
Title="MainWindow" Height="492.182" Width="499" Loaded="Window_Loaded">
<Grid>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="My Rectangle">
<StackPanel Width="50" Height="50">
<Rectangle Fill="Blue" Width="50" Height="50" Margin="0,0,0,0" Stroke="Black"/>
</StackPanel>
</MenuItem>
</Menu>
</DockPanel>
</Grid>
</Window>
Screenshot of Main Window [with design and run-time view]: In the menu item I need to display the blue rectangle only
I believe what you need to do is to override the default control template of Menu Item . So i have taken the default control template and modified it remove the icon area from the template and applied that on the control
<Window.Resources>
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon" Content="{TemplateBinding Icon}" ContentSource="Icon" HorizontalAlignment="Center" Height="16" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="0"/>
<Path x:Name="GlyphPanel" Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z" Fill="{TemplateBinding Foreground}" FlowDirection="LeftToRight" Visibility="Collapsed" VerticalAlignment="Center"/>
<ContentPresenter ContentTemplate="{TemplateBinding HeaderTemplate}" Content="{TemplateBinding Header}" Grid.Column="1" ContentStringFormat="{TemplateBinding HeaderStringFormat}" ContentSource="Header" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Bottom">
<Border x:Name="SubMenuBorder" BorderBrush="#FF999999" BorderThickness="1" Padding="0" Background="#FFF0F0F0" Width="Auto" >
<ScrollViewer x:Name="SubMenuScrollViewer" Padding="0" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=SubMenuBorder}" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
</Canvas>
<Rectangle Fill="#FFD7D7D7" HorizontalAlignment="Left" Width="1"/>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter Property="PopupAnimation" TargetName="PART_Popup" Value="None"/>
</Trigger>
<Trigger Property="Icon" Value="{x:Null}">
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Visibility" TargetName="GlyphPanel" Value="Visible"/>
<Setter Property="Visibility" TargetName="Icon" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter Property="Background" TargetName="templateRoot" Value="#3D26A0DA"/>
<Setter Property="BorderBrush" TargetName="templateRoot" Value="#FF26A0DA"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="#FF707070"/>
<Setter Property="Fill" TargetName="GlyphPanel" Value="#FF707070"/>
</Trigger>
<Trigger Property="CanContentScroll" SourceName="SubMenuScrollViewer" Value="False">
<Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}"/>
<Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
And the code for the menu item will be as given below
<DockPanel>
<Menu DockPanel.Dock="Top" >
<MenuItem Header="My Rectangle" Template="{DynamicResource MenuItemControlTemplate1}" >
<Rectangle Fill="Blue" Width="200" Height="30" Margin="-35,0,-50,0" Stroke="Black"/>
<Rectangle Fill="Red" Width="200" Height="30" Margin="-35,0,-50,0" Stroke="Black"/>
</MenuItem>
</Menu>
</DockPanel>
As you can see i have applied the margin for the rectangle, it you remove that then you will be able to see padding at the left and right side.
This is my Style:
<Style TargetType="{x:Type Menu}" x:Key="StandardMenu">
<Style.Resources>
<Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="Separator">
<Setter Property="Height" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Separator">
<Border BorderBrush="{StaticResource MenuSeparatorBorderBrush}" BorderThickness="1" Margin="25,0,0,0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
<Setter Property="FontSize" Value="{DynamicResource ApplicationFontSize}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<!--Border 1-->
<Border x:Name="Border" Background="Transparent" BorderBrush="Transparent" CornerRadius="2" BorderThickness="1" SnapsToDevicePixels="False">
<Grid x:Name="Grid">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Col0" MinWidth="17" Width="Auto" SharedSizeGroup="MenuItemIconColumnGroup"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuTextColumnGroup"/>
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup"/>
<ColumnDefinition x:Name="Col3" Width="14"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" x:Name="Icon" VerticalAlignment="Center" ContentSource="Icon"/>
<ContentPresenter Grid.Column="1" Margin="{TemplateBinding Padding}" x:Name="HeaderHost" RecognizesAccessKey="True" ContentSource="Header" VerticalAlignment="Center"/>
<ContentPresenter Grid.Column="2" Margin="8,1,8,1" x:Name="IGTHost" ContentSource="InputGestureText" VerticalAlignment="Center"/>
<Grid Grid.Column="3" Margin="4,0,6,0" x:Name="ArrowPanel" VerticalAlignment="Center">
<Path x:Name="ArrowPanelPath" HorizontalAlignment="Right" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}" Data="M0,0 L0,8 L4,4 z"/>
</Grid>
<Popup IsOpen="{Binding Path=IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Right"
HorizontalOffset="-1"
x:Name="SubMenuPopup"
Focusable="false"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
AllowsTransparency="True">
<Grid Margin="0,0,5,5">
<!--Border 2-->
<Border x:Name="SubMenuBorder" CornerRadius="5"
BorderBrush="{StaticResource MenuSeparatorBorderBrush}"
BorderThickness="1"
Background="{StaticResource SubmenuItemBackground}"
SnapsToDevicePixels="True">
<Grid x:Name="SubMenu" Grid.IsSharedSizeScope="True" Margin="2">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Cycle"/>
</Grid>
<Border.Effect>
<DropShadowEffect ShadowDepth="2" Color="Black"/>
</Border.Effect>
</Border>
<!--Border 3-->
<Border Margin="1,0,0,0"
x:Name="TransitionBorder"
Width="0"
Height="2"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Background="{StaticResource SubmenuItemBackground}"
SnapsToDevicePixels="False"
BorderThickness="1"
BorderBrush="{StaticResource SubmenuItemBackground}"/>
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true">
// Here i want to see my icon/image
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource LightBackground}"/>
<Setter Property="Foreground" Value="{StaticResource Foreground}"/>
</Style>
My View model has this Property called IsSelected and when this bool value is true i want to see my image from my Resources folder.
So i know my trigger should be something like that or similar:
<DataTrigger Binding="{Binding IsSelected}" Value="true">
// Here i want to see my icon/image
</DataTrigger>
But where i need to add this image insode my Style ?
update
This is my Menu:
<Menu Name="menuInterfaces" ItemsSource="{Binding MenuItems}" Margin="0,8,0,0" Style="{StaticResource StandardMenu}">
<Menu.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type Menu:MenuItemViewModel}" ItemsSource="{Binding Path=MenuItems}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding Width}"/>
<ColumnDefinition Width="{Binding Width}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="pack://application:,,,/Resources/checked_lightslategray.ico"
Width="12"
Height="12"
Grid.Column="0"
Margin="0,0,0,0">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Text="{Binding Description}"
Grid.Column="2"
Margin="0,0,0,0"/>
</Grid>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
</Menu>
Result:
enter image description here
You haven't specified where the image is supposed to go so I'll assume it's meant to go in the left-most column of your grid. You achieve this by styling the image and adding your DataTrigger to that instead:
<Style x:Key="MenuImageStyle" TargetType="{x:Type Image}">
<Setter Property="Source" Value="check.png" /> <!--Image filename-->
<Setter Property="Visibility" Value="Hidden" /> <!--Default value-->
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="true">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
And then you just add the image to your grid elements:
<Image Grid.Column="0" Style="{StaticResource MenuImageStyle}" />
I'm in the process of creating a dark ui for my application, and came across something interesting while using Visual Studio as a point of reference. I noticed they render their MenuItems almost as if they're Tabs in a Tabcontrol. Here's a picture:
And here's what mine looks like:
I know it's probably hard to see because everything is sort of the same color, so I went ahead and made another modified image to better highlight the area.
As you can hopefully see, Visual studio draws a border around the MenuItem, and then doesnt draw a border directly below it, for the drop down children. How does Visual Studio do it, though? How could I achieve it? Here's my template:
<Style x:Key="{x:Type Menu}" TargetType="Menu">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="#f1f1f1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Menu">
<Border x:Name="MainMenu" Background="#2d2d30">
<StackPanel
ClipToBounds="True"
IsItemsHost="True"
Orientation="Horizontal" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border
x:Name="templateRoot"
Height="16"
Background="{TemplateBinding Background}"
BorderBrush="#535353"
SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter
Grid.Column="1"
Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Popup
x:Name="PART_Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Bottom"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
<Border
x:Name="SubMenuBorder"
Padding="2"
Background="#1b1b1c"
BorderBrush="#595959"
BorderThickness="1">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas
Width="0"
Height="0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Rectangle
x:Name="OpaqueRect"
Width="{Binding ActualWidth, ElementName=SubMenuBorder}"
Height="{Binding ActualHeight, ElementName=SubMenuBorder}"
Fill="{Binding Background, ElementName=SubMenuBorder}" />
</Canvas>
<ItemsPresenter
x:Name="ItemsPresenter"
Grid.IsSharedSizeScope="True"
KeyboardNavigation.DirectionalNavigation="Cycle"
KeyboardNavigation.TabNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter TargetName="PART_Popup" Property="PopupAnimation" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#3e3e40" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#2C2C2C" />
</Trigger>
<Trigger SourceName="SubMenuScrollViewer" Property="CanContentScroll" Value="False">
<Setter TargetName="OpaqueRect" Property="Canvas.Top" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}" />
<Setter TargetName="OpaqueRect" Property="Canvas.Left" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#1b1b1c" />
<Setter Property="Header" Value="Test" />
<Setter Property="BorderBrush" Value="#2C2C2C" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="MenuItemControlTemplate2" TargetType="{x:Type MenuItem}">
<Border
x:Name="templateRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Grid Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="Auto"
MinWidth="22"
SharedSizeGroup="MenuItemIconColumnGroup" />
<ColumnDefinition Width="13" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<ContentPresenter
x:Name="Icon"
Width="16"
Height="16"
Margin="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}"
ContentSource="Icon"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Border
x:Name="GlyphPanel"
Width="22"
Height="22"
Margin="-1,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#3D26A0DA"
BorderBrush="#FF26A0DA"
BorderThickness="1"
ClipToBounds="False"
Visibility="Hidden">
<Path
x:Name="Glyph"
Width="10"
Height="11"
Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z"
Fill="#FF212121"
FlowDirection="LeftToRight" />
</Border>
<ContentPresenter
x:Name="menuHeaderContainer"
Grid.Column="2"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock
x:Name="menuGestureText"
Grid.Column="4"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Opacity="0.7"
Text="{TemplateBinding InputGestureText}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="BorderBrush" Value="Orange" />
<Setter TargetName="templateRoot" Property="Background" Value="Yellow" />
<Setter TargetName="menuHeaderContainer" Property="TextBlock.Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="#FF707070" />
<Setter TargetName="Glyph" Property="Fill" Value="#FF707070" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted" Value="True" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<Setter TargetName="templateRoot" Property="Background" Value="#0A000000" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#21000000" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
In order to figure out what's going on inside Visual Studio, I started two instances of Visual Studio 2017 and attached one to the other's process which allowed me to use the Live Visual Tree tool to inspect the controls (presumably you could use Snoop for this as well).
It turns out that the menu popup in Visual Studio appears to be offset so that it overlays the menu bar and a small box of some sort is drawn to achieve the continuous tab look. This is especially noticeable if you use the Properties window to tweak the VerticalOffset property of the popup so that it is separated from the main menu.
Finding the Popup in the Visual Tree:
Changing the VerticalOffset from its original -2 to a positive number:
And the resulting popup:
If you look at the top left of the now separated menu popup you should be able to see a small extension of the popup that, when the VerticalOffset was -2 originally, overlapped the parent MenuItem border creating the illusion of a single tab-like control.
Knowing this, creating a rudimentary version of Visual Studio's solution is fairly straightforward:
<Window x:Class="MenuItemTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MenuItemTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="525"
Height="350"
mc:Ignorable="d">
<Window.Resources>
<local:SubtractingConverter x:Key="SubtractingConverter" />
<Style x:Key="{x:Type Menu}" TargetType="Menu">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="#f1f1f1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Menu">
<Border x:Name="MainMenu" Background="#2d2d30">
<StackPanel ClipToBounds="True"
IsItemsHost="True"
Orientation="Horizontal" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="MenuItemControlTemplate1" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot"
Height="16"
Background="{TemplateBinding Background}"
BorderBrush="#535353"
SnapsToDevicePixels="True">
<Grid VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="1"
Margin="{TemplateBinding Padding}"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Popup x:Name="PART_Popup"
AllowsTransparency="True"
Focusable="False"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Bottom"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
<Grid>
<Border x:Name="SubMenuBorder"
Padding="2"
Background="#1b1b1c"
BorderBrush="#595959"
BorderThickness="1">
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas Width="0"
Height="0"
HorizontalAlignment="Left"
VerticalAlignment="Top">
<Rectangle x:Name="OpaqueRect"
Width="{Binding ActualWidth, ElementName=SubMenuBorder}"
Height="{Binding ActualHeight, ElementName=SubMenuBorder}"
Fill="{Binding Background, ElementName=SubMenuBorder}" />
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter"
Grid.IsSharedSizeScope="True"
KeyboardNavigation.DirectionalNavigation="Cycle"
KeyboardNavigation.TabNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Grid>
</ScrollViewer>
</Border>
<Rectangle Width="{TemplateBinding ActualWidth,
Converter={StaticResource SubtractingConverter},
ConverterParameter=1}"
Height="2"
Margin="1,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Fill="{Binding Background, ElementName=SubMenuBorder}" />
</Grid>
</Popup>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSuspendingPopupAnimation" Value="True">
<Setter TargetName="PART_Popup" Property="PopupAnimation" Value="None" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#3e3e40" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#2C2C2C" />
</Trigger>
<Trigger SourceName="SubMenuScrollViewer" Property="CanContentScroll" Value="False">
<Setter TargetName="OpaqueRect" Property="Canvas.Top" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}" />
<Setter TargetName="OpaqueRect" Property="Canvas.Left" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}" />
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter TargetName="templateRoot" Property="Background" Value="#1b1b1c" />
<Setter Property="Header" Value="Test" />
<Setter Property="BorderBrush" Value="#2C2C2C" />
<Setter Property="BorderThickness" Value="1" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<ControlTemplate x:Key="MenuItemControlTemplate2" TargetType="{x:Type MenuItem}">
<Border x:Name="templateRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Grid Margin="-1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"
MinWidth="22"
SharedSizeGroup="MenuItemIconColumnGroup" />
<ColumnDefinition Width="13" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<ContentPresenter x:Name="Icon"
Width="16"
Height="16"
Margin="3"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Icon}"
ContentSource="Icon"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<Border x:Name="GlyphPanel"
Width="22"
Height="22"
Margin="-1,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Background="#3D26A0DA"
BorderBrush="#FF26A0DA"
BorderThickness="1"
ClipToBounds="False"
Visibility="Hidden">
<Path x:Name="Glyph"
Width="10"
Height="11"
Data="F1M10,1.2L4.7,9.1 4.5,9.1 0,5.2 1.3,3.5 4.3,6.1 8.3,0 10,1.2z"
Fill="#FF212121"
FlowDirection="LeftToRight" />
</Border>
<ContentPresenter x:Name="menuHeaderContainer"
Grid.Column="2"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<TextBlock x:Name="menuGestureText"
Grid.Column="4"
Margin="{TemplateBinding Padding}"
VerticalAlignment="Center"
Opacity="0.7"
Text="{TemplateBinding InputGestureText}" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Icon" Value="{x:Null}">
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="IsHighlighted" Value="True">
<Setter TargetName="templateRoot" Property="BorderBrush" Value="Orange" />
<Setter TargetName="templateRoot" Property="Background" Value="Yellow" />
<Setter TargetName="menuHeaderContainer" Property="TextBlock.Foreground" Value="Black" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="#FF707070" />
<Setter TargetName="Glyph" Property="Fill" Value="#FF707070" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsHighlighted" Value="True" />
<Condition Property="IsEnabled" Value="False" />
</MultiTrigger.Conditions>
<Setter TargetName="templateRoot" Property="Background" Value="#0A000000" />
<Setter TargetName="templateRoot" Property="BorderBrush" Value="#21000000" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Menu Background="#2d2d30">
<MenuItem Header="Tools" Template="{StaticResource MenuItemControlTemplate1}">
<MenuItem Padding="0"
Background="#2d2d30"
Header="Test"
Template="{StaticResource MenuItemControlTemplate2}" />
</MenuItem>
<MenuItem Header="Whatever" Template="{StaticResource MenuItemControlTemplate1}">
<MenuItem Padding="0"
Background="#2d2d30"
Header="Test"
Template="{StaticResource MenuItemControlTemplate2}" />
</MenuItem>
</Menu>
</Grid>
</Window>
This is basically the same style and templates that you gave above with the addition of a Rectangle within the MenuItemControlTemplate1 ControlTemplate and a Grid so that both it and the existing Border can be contained within the popup. The SubtractingConverter is just a simple IValueConverter that subtracts the ConverterParameter from the Value... nothing fancy. I've also gone ahead and thrown it in a window for testing. When I run this test program I now get this:
Since I don't have all of your styles obviously not all of the colors are going to be correct, but you'll notice that the menu you were concerned about now appears to be one continuous tab like in Visual Studio.
Now this is not a full solution. There are obvious minor details such as a missing border around the parent "Tools" and "Whatever" menus, but more critically you still need to account for the Popup changing its position due to overlap with the monitor edges when placing the Rectangle.
If you move the application window to the bottom of the screen, the Popup class will open the menu instance above the "Tools" menu rather than below, which will obviously result in the Rectangle being misplaced. Similarly, opening the menu when the window is again the right edge of the screen will once again cause the Rectangle to be misplaced due to the change in popup position. Even Visual Studio 2017 doesn't properly account for this case as you can see below:
Now, maybe handling the basic use case is enough for you in which case, great! If you want to go further and handle repositioning, resizing, and/or hiding/showing the rectangle so that it looks perfect no matter what weird position the user opens a menu in, then I really see no way to do this cleanly without some actual C# code. I suspect this is at least one of the things that the VSMenuItem class in the Live Visual Tree of Visual Studio shown previously does over and above the bog standard MenuItem class. Implementing that functionality is really outside the scope of the original question, but hopefully this at least made clear how they pulled it off.
Set the background colour of that menu item to the colour that you want, and the foreground colour to white.
I want to use a ComboBox with different CornerRadius, how can I change that simply? I've tried with Style and ControlTemplate, but without any success.
I don't know if this is simple, but creating a ControlTemplate based on the default ComboBox should do the trick. Here is an example:
<Style x:Key="ComboBoxTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border CornerRadius="5,0,0,5"
BorderThickness="1"
Background="{TemplateBinding Background}"
BorderBrush="Black">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MaxWidth="18"/>
</Grid.ColumnDefinitions>
<TextBox Name="PART_EditableTextBox"
Style="{StaticResource ComboBoxTextBoxStyle}"
Padding="5,0,0,0"
Height="{TemplateBinding Height}"/>
<ToggleButton Grid.Column="1" Margin="0"
Height="{TemplateBinding Height}"
Style="{StaticResource ComboBoxButtonStyle}"
Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
<Path Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"
Fill="DodgerBlue" />
</ToggleButton>
<ContentPresenter Name="ContentSite"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="5,0,0,0"/>
<Popup Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Grid Name="DropDown"
SnapsToDevicePixels="True"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border
x:Name="DropDownBorder"
BorderThickness="1"
CornerRadius="5"
Background="Azure"
BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You will need to define the VisualStates/Triggers in the Style if required
Thanks Richard E!
Here a clean version of Richard E's answer:
<Style x:Key="ComboBoxTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border CornerRadius="5,0,0,5"
BorderThickness="1,1,0,1"
Background="{TemplateBinding Background}"
BorderBrush="Black">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ComboBoxButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border
Background="White"
x:Name="border"
CornerRadius="0,5,5,0"
BorderThickness="0,1,1,1"
BorderBrush="Black">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RoundComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MaxWidth="18"/>
</Grid.ColumnDefinitions>
<TextBox Name="PART_EditableTextBox"
Style="{StaticResource ComboBoxTextBoxStyle}"
Padding="5,0,0,0"
Height="{TemplateBinding Height}"/>
<ToggleButton Grid.Column="1" Margin="0"
Height="{TemplateBinding Height}"
Style="{StaticResource ComboBoxButtonStyle}"
Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
<Path Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"
Fill="DodgerBlue" />
</ToggleButton>
<ContentPresenter Name="ContentSite"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="5,0,0,0"/>
<Popup Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Grid Name="DropDown"
SnapsToDevicePixels="True"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border
x:Name="DropDownBorder"
BorderThickness="1"
CornerRadius="5"
Background="Azure"
BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
UPDATE:
After changing to get my custom version I found out it wasn't the best example to start with (editable combobox, not optimized, missing style etc ...), I found a good example on this website:
http://www.wpfhelper.com/index.php/styles-in-wpf/combobox/15-combobox-style-in-wpf
And here my custom version (to implement in Resources ex: in tag <UserControl.Resources>):
<Style x:Key="ComboBoxToggleButton" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="32" />
</Grid.ColumnDefinitions>
<Border
x:Name="Border"
Grid.ColumnSpan="2"
CornerRadius="8"
Background="{TemplateBinding Background}"
BorderBrush="#F6F6F6"
BorderThickness="1"
/>
<Path
x:Name="Arrow"
Grid.Column="1"
Fill="{TemplateBinding Foreground}"
Stroke="{TemplateBinding Foreground}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="TextBox">
<Border x:Name="PART_ContentHost" Focusable="True" />
</ControlTemplate>
<Style x:Key="theComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="#333" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="Background" Value="White" />
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="FontSize" Value="13" />
<Setter Property="MinWidth" Value="150"/>
<Setter Property="MinHeight" Value="35"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton
Cursor="Hand"
Name="ToggleButton"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Style="{StaticResource ComboBoxToggleButton}"
Grid.Column="2"
Focusable="false"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"/>
<ContentPresenter
Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="10,3,30,3"
VerticalAlignment="Center"
HorizontalAlignment="Left" />
<TextBox x:Name="PART_EditableTextBox"
Style="{x:Null}"
Template="{StaticResource ComboBoxTextBox}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="3,3,23,3"
Focusable="True"
Visibility="Hidden"
IsReadOnly="{TemplateBinding IsReadOnly}"/>
<Popup
Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Grid
Name="DropDown"
SnapsToDevicePixels="True"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border
CornerRadius="8"
x:Name="DropDownBorder"
Background="White"
BorderThickness="1"
BorderBrush="#F6F6F6"
/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasItems" Value="false">
<Setter TargetName="DropDownBorder" Property="MinHeight" Value="95"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="IsEditable" Value="true">
<Setter Property="IsTabStop" Value="false"/>
<Setter TargetName="PART_EditableTextBox" Property="Visibility" Value="Visible"/>
<Setter TargetName="ContentSite" Property="Visibility" Value="Hidden"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
</Style.Triggers>
</Style>
<Style x:Key="theComboBoxItem" TargetType="{x:Type ComboBoxItem}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="FontSize" Value="13" />
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Border
Name="Border"
Padding="5"
Margin="2"
BorderThickness="2,0,0,0"
CornerRadius="0"
Background="Transparent"
BorderBrush="Transparent">
<TextBlock TextAlignment="Left">
<ContentPresenter />
</TextBlock>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="#B3CB37"/>
<Setter TargetName="Border" Property="Background" Value="#F8FAEB"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here the Combobox and style implementation:
<ComboBox
FontSize="13"
Style="{DynamicResource theComboBox}"
Padding="15,5,15,5"
HorizontalContentAlignment="Left"
VerticalAlignment="Center"
MinWidth="100"
MaxWidth="375"
Grid.Row="1"
Grid.Column="1"
ItemContainerStyle="{DynamicResource theComboBoxItem}"
>
<ComboBoxItem>Available</ComboBoxItem>
<ComboBoxItem>Busy</ComboBoxItem>
<ComboBoxItem>On Duty</ComboBoxItem>
<ComboBoxItem>On Meeting</ComboBoxItem>
<ComboBoxItem>On Vacation</ComboBoxItem>
<ComboBoxItem>On Weekend</ComboBoxItem>
</ComboBox>
Add a ComboBox in your WPF project, right click on it and select EditTemplate> Edit a copy...
Choose a name for style and click ok.
vs create a ComboBoxTemplate for ComboBox.
now you can add a border and set desired CornerRadius to ComboBoxTemplate.
I would like to style my expander control in such way that it can have a drop down panel like that of combobox control.
Drop down panel should be like it can overlay above other items like that of combobox.
Here's the XAML style for expander which i'm using :
<Style TargetType="{x:Type Expander}">
<Setter Property="Background" Value="{StaticResource Brush_ButtonFill}"/>
<Setter Property="BorderBrush" Value="{StaticResource Brush_ContainerButtonBorder}"/>
<Setter Property="Foreground" Value="{StaticResource Brush_FontReadonly}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" x:Name="ContentRow"/>
</Grid.RowDefinitions>
<Border Visibility="Collapsed" Grid.Row="1" x:Name="ExpandSite" Background="{StaticResource BrushTransparent}" BorderBrush="{StaticResource Brush_DropdownShadow}">
<ContentPresenter Focusable="false"/>
</Border>
<Border Grid.Row="0" x:Name="Border" Background="{StaticResource Brush_ButtonBorder}" Visibility="Collapsed" BorderThickness="1"/>
<ToggleButton Template="{StaticResource ExpanderToggleButtonControlTemplate}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" OverridesDefaultStyle="True" Background="{StaticResource Brush_ButtonFill}" BorderBrush="{StaticResource Brush_ButtonBorder}" BorderThickness="{TemplateBinding BorderThickness}" Foreground="{StaticResource Brush_ButtonBorder}" d:LayoutOverrides="VerticalAlignment" />
<ContentPresenter Margin="15,2,2,2" RecognizesAccessKey="True" ContentSource="Header" VerticalAlignment="Center" HorizontalAlignment="Left" IsHitTestVisible="False"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter Property="Visibility" Value="Visible" TargetName="ExpandSite"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ExpanderStyle_Dropdown" TargetType="{x:Type Expander}" BasedOn="{StaticResource TextStyle_BaseControl}">
<Setter Property="Background" Value="{StaticResource Brush_ButtonFill}"/>
<Setter Property="BorderBrush" Value="{StaticResource Brush_ButtonBorder}"/>
<Setter Property="Foreground" Value="Black"/>
<!--<Setter Property="Foreground" Value="{StaticResource Brush_FontReadonly}"/>-->
<Setter Property="FontSize" Value="{StaticResource FontSizeMedium}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="54"/>
<RowDefinition Height="*" x:Name="ContentRow"/>
</Grid.RowDefinitions>
<Border Visibility="Collapsed" Grid.Row="1" x:Name="ExpandSite" Background="{StaticResource Brush_ButtonShadow}" CornerRadius="0,0,5,5" Margin="0,-5,0,0" Panel.ZIndex="1000">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Focusable="false" Margin="5,10,5,5" Panel.ZIndex="1000"/>
</Border>
<Border Grid.Row="0" x:Name="Border" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="7" Padding="5" Background="{StaticResource Brush_CZBlueSelected}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Border Grid.Row="0" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5,0,0,5" Padding="5" Grid.ColumnSpan="1" Margin="0,0,1,0"/>
<Border x:Name="Shadow" CornerRadius="5" Padding="5" Grid.ColumnSpan="2" BorderBrush="{StaticResource Brush_SearchinputBorder}" BorderThickness="0,0,0,2" Margin="0,0,0,-2"/>
<ToggleButton Template="{StaticResource ExpanderToggleButtonControlTemplate_DropDown}" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" OverridesDefaultStyle="True" Background="{StaticResource Brush_ButtonFill}" BorderBrush="{StaticResource Brush_ButtonBorder}" Grid.Column="1" BorderThickness="{TemplateBinding BorderThickness}" Foreground="{StaticResource Brush_ButtonBorder}" Margin="1,0,0,0" Height="44" />
<ContentPresenter Margin="4" RecognizesAccessKey="True" ContentSource="Header" VerticalAlignment="Center" HorizontalAlignment="Center" IsHitTestVisible="False"/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter Property="Visibility" Value="Visible" TargetName="ExpandSite"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now using the same in XAML screen as:
<Expander Name="expanderNextScan" Header="{Binding ElementName=listBoxExpander,Path=SelectedItem.Content}" ExpandDirection="Up" Grid.Column="3" Height="54" Width="Auto" Style="{DynamicResource ExpanderStyle_Dropdown}" >
<Grid Background="#FFE5E5E5" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<ListBox x:Name="listBoxExpander" Height="100" Width="{Binding ElementName=expanderNextScan,Path=ActualWidth}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Visible" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="0,-10,0,0" Panel.ZIndex="5">
<ListBoxItem Content="Go to Next Scan" FontSize="{StaticResource FontSizeMedium}" IsSelected="True"/>
<ListBoxItem FontSize="{StaticResource FontSizeMedium}" Content="Print with preview" />
<ListBoxItem FontSize="{StaticResource FontSizeMedium}" Content="Export as PDF"/>
<ListBoxItem FontSize="{StaticResource FontSizeMedium}" Content="Export to DICOM"/>
</ListBox>
</Grid>
</Expander>
Now want to style it in such a way that the list box coming in the expander drop down should have a z-index greater than the other controls on the screen such that it can overlay over other controls like that of combobox dropdown.
Please reply ASAP.