dotnet / wpf

WPF is a .NET Core UI framework for building Windows desktop applications.
MIT License
7.07k stars 1.16k forks source link

WPF known issues: Separator does not apply the implicit style in Menu #7268

Closed lindexi closed 1 year ago

lindexi commented 1 year ago

I'm not sure if this issues is designed this way. When the Separator in the Menu, such as ContextMenu or Menu, the Separator will not apply the implicit style. Just as the code:

            <ContextMenu>
                <ContextMenu.Resources>
                    <Style TargetType="Separator">
                        <Setter Property="Margin" Value="10,10,10,10"></Setter>
                    </Style>
                </ContextMenu.Resources>
                <Separator></Separator>
            </ContextMenu>

Run this code, and you can find the Separator do not use the style which margin do not be changed.

But when we set the key to the style resource and make the Separator reference this style by StaticResource, the Separator can apply the style and we can find the margin of Separator be changed.

            <ContextMenu>
                <ContextMenu.Resources>
                    <Style x:Key="SeparatorStyle" TargetType="Separator">
                        <Setter Property="Margin" Value="10,10,10,10"></Setter>
                    </Style>
                </ContextMenu.Resources>
                <Separator Style="{StaticResource SeparatorStyle}"></Separator>
            </ContextMenu>

Actual behavior:

As the description says, the Separator does not apply the implicit style in Menu.

Expected behavior:

The Separator can work as the other control.

Minimal repro:

My demo code: https://github.com/lindexi/lindexi_gd/tree/b820847a1af20370de28a1e73e32df9561a98ecc/HayhachujedaKikunayreefee


Why

Because the WPF specially sets the Separator style in

https://github.com/dotnet/wpf/blob/1aab9e3f42dbf550797bff97a32f2dbfb61a3198/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L1344-L1353

But I can't understand why this code is doing this. Could any one tell me?

czdietrich commented 1 year ago

Hey, I hope I completely understand your problem.

A Separator can be used in several places, e. g. in a (Context)Menu or a ToolBar. Since both places need completely different representations for a Separator, the WPF framework needs to make a distinction depending on the area where it is used. All these item controls will set an explicit style key (if there is not already an explicit style defined) on the Separator to enable different style templates for this control.

If you want to define an implicit style for a Separator you need to use the related style key, e. g. MenuItem.SeparatorStyleKey for a (Context)Menu.

A small sample to define an implicit style:

<Window x:Class="TestContextMenuSeparatorStyle.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Window.Resources>
        <Style x:Key="{x:Static MenuItem.SeparatorStyleKey}" TargetType="Separator">
            <Setter Property="Background" Value="Tomato" />
        </Style>
    </Window.Resources>

    <Grid Background="White">
        <Grid.ContextMenu>
            <ContextMenu>
                <MenuItem Header="Item 1" />
                <Separator />
                <MenuItem Header="Item 2" />
            </ContextMenu>
        </Grid.ContextMenu>
    </Grid>
</Window>

Results in: image

I hope this answers your question.

lindexi commented 1 year ago

Thank you @czdietrich

A Separator can be used in several places, e. g. in a (Context)Menu or a ToolBar. Since both places need completely different representations for a Separator, the WPF framework needs to make a distinction depending on the area where it is used.

And I'd rather know the reason for the code.

anjali-wpf commented 1 year ago

@lindexi - @czdietrich has already explained that Separator is used at multiple places with different representations thats why we allow explicit styles to make a distinction. And for the code snippet which you are referring for Separator style, any changes to style applied directly to the element will have highest precedence, that is why we are setting it that way. You need to define implicit style to make it work. This is as per the design.

lindexi commented 1 year ago

Thank you. @anjalisheel-wpf @czdietrich