Search code examples
wpfxamlitemcontainerstyle

WPF Style's property cannot be applied to MenuItem when its ItemContainerStyle has the same one


In my view, I have defined 2 MenuItem under ContextMenu.

Both "Menu 1" and "Menu 2" are set to same Style which defines Background and Foreground color.

The only difference is that "Menu 2" is a single menu but "Menu 1" also has sub-menus and sub-menu styles (in "ItemContainerStyle").

View.xaml:

            <contextMenuButton:ContextMenuButton Grid.Column="0" 
                                                 VerticalAlignment="Top" 
                                                 HorizontalAlignment="Right"
                                                 Background ="Transparent" 
                                                 Margin="0, 0, 150, 0"
                                                 BorderThickness="0" 
                                                 Foreground ="Chocolate" 
                                                 FontSize="13">
                <contextMenuButton:ContextMenuButton.Content>
                    <TextBlock Text="Menu Button" />
                </contextMenuButton:ContextMenuButton.Content>
                <contextMenuButton:ContextMenuButton.Menu >
                    <ContextMenu Style="{StaticResource ContextMenuStyle1}">
                        <MenuItem Header="Menu 1"
                                  Style="{StaticResource MenuItemStyle1}"
                                  ItemContainerStyle="{StaticResource MenuItemStyle2}"
                                  ItemsSource="{StaticResource SubMenuItems1}"/>
                        <MenuItem Header="Menu 2"
                                  Style="{StaticResource MenuItemStyle1}"/>
                    </ContextMenu>
                </contextMenuButton:ContextMenuButton.Menu>
            </contextMenuButton:ContextMenuButton>

ResourceDictionary.xaml:

    <Style TargetType="ContextMenu"
           x:Key="ContextMenuStyle1">
        <Setter Property="Placement"
                Value="Bottom" />
    </Style>
    <Style x:Key="MenuItemStyle1" TargetType="MenuItem">
        <Setter Property="Foreground"
                Value="LightGreen"/>
        <Setter Property="Background"
                Value="Red"/>
    </Style>
    <Style x:Key="MenuItemStyle2" TargetType="MenuItem">
        <Setter Property="Foreground"
                Value="Blue"/>
    </Style>
    <collections:ArrayList x:Key="SubMenuItems1" >
        <MenuItem Header="First"/>
        <MenuItem Header="Second"/>
        <MenuItem Header="Third"/>
    </collections:ArrayList>

The result shows "Menu 2"'s Background and Foreground color are set as expected, but "Menu 1"'s Foreground color cannot be set. I suspect the reason is in "Menu 1"'s sub-menu style, it has Foreground too, so it is somehow conflict with the same property in parent menu (sub menu's Foreground color is set successfully though).

enter image description here

So in this scenario, how can I set parent menu's own style? This is my first question in SOF, I hope I have described the issue clearly and thank you guys so much for the help in advance!

I have tried the apply x:Shared = False to MenuItemStyle1 and MenuItemStyle2 but it doesn't work (problem remains the same)


Solution

  • Problem is clear now. So in my application context, the "MenuItem" is applying a customized Style from a ResouceDictionary file.

    In that customized Style, "Template" property is set with a value of a "ControlTemplate". In its ControlTemplate.Triggers, it define the Foreground and other properties (such as the Visibility of sub arrow at right most) depend on if the MenuItem has Child or not.

    In WPF, for a same property of a UI element (such as Foreground), the value defined in Template has higher priority to override the value defined directly in Style.

    So back to my case, both "Menu1" and "Menu2"'s Foreground is defined by explicit Style (MenuItemStyle1). "Menu2" Foreground is set by MenuItemStyle1 but "Menu1"'s Foreground is still set according to Template's ControlTemplate.Triggers (which is Black), rather than its explicit Style (which is LightGreen).