Skip to content

Can't override style of content within templated control #7792

@michael-hawker

Description

@michael-hawker

Describe the bug

We're working on the new SettingsExpander control in Windows Community Toolkit Labs: CommunityToolkit/Labs-Windows#253

As part of this we need to ensure that ToggleSwitch controls as part of the content get the proper styling to align to the design guidelines for this pattern:

image

Not this:

image

We need this to be done implicitly so developers don't have to add extra styling for each common option they add to their app. The style is part of using this contract in the control. We've done this in other places and scenarios, but this specific one is failing and we don't understand the differences in the setup here causing the issue.

Steps to reproduce the bug

Minimal repro (both UWP and WinUI 3):

<Page
    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"
    mc:Ignorable="d">

    <Page.Resources>
        <Style x:Key="RightAlignedCompactToggleSwitchStyle"
           BasedOn="{StaticResource DefaultToggleSwitchStyle}"
           TargetType="ToggleSwitch">
            <Setter Property="Background" Value="Red"/>
        </Style>

        <Style x:Key="MyUserControl" TargetType="Button"> <!-- Target Type doesn't matter here, using as a makeshift Templated Control in XAML Studio -->
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <!-- For some reason template binding is negating the resource override here -->
                        <ContentPresenter Content="{TemplateBinding Content}">
                            <ContentPresenter.Resources>
                                <Style TargetType="ToggleSwitch" BasedOn="{StaticResource RightAlignedCompactToggleSwitchStyle}"/>
                            </ContentPresenter.Resources>
                        </ContentPresenter>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style x:Key="MyUserControlHardcoded" TargetType="Button">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <ContentPresenter>
                            <ContentPresenter.Content>
                                <ToggleSwitch/>
                            </ContentPresenter.Content>
                            <ContentPresenter.Resources>
                                <Style TargetType="ToggleSwitch" BasedOn="{StaticResource RightAlignedCompactToggleSwitchStyle}"/>
                            </ContentPresenter.Resources>
                        </ContentPresenter>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Page.Resources>

    <StackPanel Padding="40" Spacing="16">
        <!-- Doesn't Work as expected -->
        <Button Style="{StaticResource MyUserControl}">
            <ToggleSwitch/>
        </Button>
        <!-- Works within template -->
        <Button Style="{StaticResource MyUserControlHardcoded}"/>
        <!-- Works outside of a control -->
        <ContentPresenter>
            <ContentPresenter.Content>
                <ToggleSwitch/>
            </ContentPresenter.Content>
            <ContentPresenter.Resources>
                <Style TargetType="ToggleSwitch" BasedOn="{StaticResource RightAlignedCompactToggleSwitchStyle}"/>
            </ContentPresenter.Resources>
        </ContentPresenter>

        <!-- expected result -->
        <ToggleSwitch Style="{StaticResource RightAlignedCompactToggleSwitchStyle}"/>
    </StackPanel>

</Page>

We also tried not using Template Binding and setting the content property of the inner ContentPresenter in OnApplyTemplate but that didn't work as expected either. (It's also not tied to ToggleSwitch as the content either, could be a Button just an example for our scenario.)

image

All controls should have red background.

Expected behavior

Style is properly overridden and picked up by the content of the control.

Screenshots

No response

NuGet package version

No response

Windows app type

  • UWP
  • Win32

Device form factor

Desktop

Windows version

Windows 10 (21H2): Build 19044

Additional context

Related other issues:

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions