Search code examples
wpfxamldatagrid

Giving my ContextMenu style treatment not working


I have a WPF App and I have a context menu showing up when I right click on any row in my datagrid. It works 100% but I want to mess with the style and give a nice dark theme to this context menu. This was my first ever attempt at making a context menu in dark theme.

<DataGrid>
<DataGrid.Resources>
 ...
</DataGrid.Resources>
<DataGrid.ContextMenu>
                    <ContextMenu BorderBrush="Transparent" BorderThickness="0" Background="#FF484848" Foreground="White">
                        <MenuItem Header="Item 1" BorderBrush="Transparent" BorderThickness="0" Background="#FF484848">
                            <MenuItem.Icon>
                                <Image Source="/Foo.Bar.MyAwesomeApp;component/Resources/icon-1.png"/>
                            </MenuItem.Icon>
                        </MenuItem>
                        <MenuItem Header="Item 2" BorderBrush="Transparent" BorderThickness="0" Background="#FF484848">
                            <MenuItem.Icon>
                                <Image Source="/Foo.Bar.MyAwesomeApp;component/Resources/icon-2.png"/>
                            </MenuItem.Icon>
                        </MenuItem>
                        <Separator Background="#FF131313" Height="2" />
                        <MenuItem Header="Item 3" BorderBrush="Transparent" BorderThickness="0" Background="#FF484848">
                            <MenuItem.Icon>
                                <Image Source="/Foo.Bar.MyAwesomeApp;component/Resources/icon-3.png"/>
                            </MenuItem.Icon>
                        </MenuItem>
                    </ContextMenu>
                </DataGrid.ContextMenu>
<DataGrid.Columns>
   ...
</DataGrid.Columns>
</DataGrid>

All this is getting me is a context menu with the desired background color but the icon area has a light gray background taking over the icon space and when I hover over each menu item I still get the old light gray colors. In addition there's a vertical light gray bay between the icon space and the header text space and I have no idea how to change the style for that.

Has anyone been able to solve this issue? Many thanks in advance.


Solution

  • You need to write your own MenuItem.Template, you can copy default WPF template and change it.

    Default template is

        <SolidColorBrush x:Key="Menu.Static.Foreground" Color="#FF212121"/>
        <SolidColorBrush x:Key="Menu.Disabled.Foreground" Color="#FF707070"/>
        <SolidColorBrush x:Key="MenuItem.Selected.Background" Color="#3D26A0DA"/>
        <SolidColorBrush x:Key="MenuItem.Selected.Border" Color="#FF26A0DA"/>
        <SolidColorBrush x:Key="MenuItem.Highlight.Background" Color="#3D26A0DA"/>
        <SolidColorBrush x:Key="MenuItem.Highlight.Border" Color="#FF26A0DA"/>
        <SolidColorBrush x:Key="MenuItem.Highlight.Disabled.Background" Color="#0A000000"/>
        <SolidColorBrush x:Key="MenuItem.Highlight.Disabled.Border" Color="#21000000"/>
        <Geometry x:Key="Checkmark">F1 M 10.0,1.2 L 4.7,9.1 L 4.5,9.1 L 0,5.2 L 1.3,3.5 L 4.3,6.1L 8.3,0 L 10.0,1.2 Z</Geometry>
        <ControlTemplate x:Key="MenuItemTemplate1" TargetType="{x:Type MenuItem}">
            <Border x:Name="templateRoot" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Height="22" SnapsToDevicePixels="true">
                <Grid Margin="-1">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition MinWidth="22" SharedSizeGroup="MenuItemIconColumnGroup" Width="Auto"/>
                        <ColumnDefinition Width="13"/>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="30"/>
                        <ColumnDefinition SharedSizeGroup="MenuItemIGTColumnGroup" Width="Auto"/>
                        <ColumnDefinition Width="20"/>
                    </Grid.ColumnDefinitions>
                    <ContentPresenter x:Name="Icon" ContentSource="Icon" HorizontalAlignment="Center" Height="16" Margin="3" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center" Width="16"/>
                    <Border x:Name="GlyphPanel" Background="{StaticResource MenuItem.Selected.Background}" BorderThickness="1" BorderBrush="{StaticResource MenuItem.Selected.Border}" ClipToBounds="False" HorizontalAlignment="Center" Height="22" Margin="-1,0,0,0" VerticalAlignment="Center" Visibility="Hidden" Width="22">
                        <Path x:Name="Glyph" Data="{StaticResource Checkmark}" FlowDirection="LeftToRight" Fill="{StaticResource Menu.Static.Foreground}" Height="11" Width="10"/>
                    </Border>
                    <ContentPresenter x:Name="menuHeaderContainer" ContentSource="Header" Grid.Column="2" HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
                    <TextBlock x:Name="menuGestureText" Grid.Column="4" Margin="{TemplateBinding Padding}" Opacity="0.7" Text="{TemplateBinding InputGestureText}" VerticalAlignment="Center"/>
                </Grid>
            </Border>
            <ControlTemplate.Triggers>
                <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="{StaticResource MenuItem.Highlight.Background}"/>
                    <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource MenuItem.Highlight.Border}"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="False">
                    <Setter Property="TextElement.Foreground" TargetName="templateRoot" Value="{StaticResource Menu.Disabled.Foreground}"/>
                    <Setter Property="Fill" TargetName="Glyph" Value="{StaticResource Menu.Disabled.Foreground}"/>
                </Trigger>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsHighlighted" Value="True"/>
                        <Condition Property="IsEnabled" Value="False"/>
                    </MultiTrigger.Conditions>
                    <Setter Property="Background" TargetName="templateRoot" Value="{StaticResource MenuItem.Highlight.Disabled.Background}"/>
                    <Setter Property="BorderBrush" TargetName="templateRoot" Value="{StaticResource MenuItem.Highlight.Disabled.Border}"/>
                </MultiTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    

    You can get it if you click on menuitem element in xaml designer, and select Edit Template as a Copy