Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add override-aware indirection support to the XAML resource lookup system #2913

Open
Felix-Dev opened this issue Jul 15, 2020 · 3 comments
Labels
area-Resources feature proposal New feature proposal team-Markup Issue for the Markup team

Comments

@Felix-Dev
Copy link
Contributor

Felix-Dev commented Jul 15, 2020

Proposal: Add override-aware indirection support to the XAML resource lookup system

Summary

Currently, the XAML resource lookup system does not have support for override-aware indirection. By that I mean the following: If we have two resources with one resource referencing the other, the referencing resource should pick up developer-provided overrides of the referenced theme resource when in scope. To illustrate this, please take a look at the following XAML:

<!-- These resources are defined in some resource dictionary -->
<SolidColorBrush x:Key="BaseBrush" Color="LightBlue" />
<StaticResource x:Key="BaseBrushInheritor" ResourceKey="BaseBrush" />

And some XAML where these resources are consumed:

<StackPanel Orientation="Horizontal">
    <StackPanel>
        <Rectangle Fill="{StaticResource BaseBrush}" Width="150" Height="150" Margin="0,0,10,0" />
        <TextBlock Text="BaseBrush" Width="150" TextWrapping="Wrap" HorizontalAlignment="Left" />
    </StackPanel>
    <StackPanel>
        <Rectangle Fill="{StaticResource BaseBrushInheritor}" Width="150" Height="150" />
        <TextBlock Text="BaseBrushInheritor" Width="150" TextWrapping="Wrap" HorizontalAlignment="Left" />
    </StackPanel>
</StackPanel>

In the code above, we are creating two rectangles side-by-side with one rectangle consuming the referenced resource directly (BaseBrush) and the other rectangle consuming the referencing resource (BaseBrushInheritor). As we would expect, both rectangles are displayed in the correct color:
image

The issue arises when we now override the referenced resource, like so:

<StackPanel Orientation="Horizontal">
    <StackPanel.Resources>
        <SolidColorBrush x:Key="BaseBrush" Color="Orange" />
    </StackPanel.Resources>
    <StackPanel>
        <Rectangle Fill="{StaticResource BaseBrush}" Width="150" Height="150" Margin="0,0,10,0" />
        <TextBlock Text="BaseBrush" Width="150" TextWrapping="Wrap" HorizontalAlignment="Left" />
    </StackPanel>
    <StackPanel>
        <Rectangle Fill="{StaticResource BaseBrushInheritor}" Width="150" Height="150" />
        <TextBlock Text="BaseBrushInheritor" Width="150" TextWrapping="Wrap" HorizontalAlignment="Left" />
    </StackPanel>
</StackPanel>

This gives us the following result:
image

As we can see, the rectangle consuming the referenced resource (BaseBrush) correctly picked up our local override. However, the referencing resource did not. It still uses the the orginal value of the referenced theme resource, even though we have overriden that one in the correct scope. Ideally, the result here would be both rectangles displayed in an orange color.

I have attached a demo app featuring this code below.

Rationale

Adding support to the resource lookup system to pick up updates to referenced resources and make them available through the referencing resources will enable at least the following two scenarios:

  1. We would be be able to update WinUI's (theme) resources in certain cases without breaking apps of developers. For example, WinUI today ships with resources named incorrectly or imprecisely. With override-aware indirection support, we could add new resources properly named and make them reference the existing resource, ensuring that any app using the existing resource to customize its UI will still look as expected. Examples where this would be helpful can be found here, here and here (see the discussion on the proposed TopNavigationViewItemHeaderInnerMargin theme resource).
  2. We would be able to offer some "at all once" customization for related UI elements while still providing fine-grained customization support. An example for this can be found for the TextBox, ComboBox and NumberBox controls. All three controls have a Description API and the foreground appearance can be configured by overriding the SystemControlDescriptionTextForegroundBrush theme resource. In other words, overriding this resource on the app level, for example, will apply to the descriptions of all in-app TextBox, CombBox and NumberBox controls. However, for a consistent and easily discoverable lightweight-styling experience we should also think about adding specific theme resources like TextBoxDescriptionForeground, ComboBoxDescriptionForeground and NumberBoxDescriptionForeground. These three theme resources would reference the "parent" theme resource SystemControlDescriptionTextForegroundBrush so all overrides applied to it will still propagate down to its "child" theme resources while still allowing developers to pick a unique description foreground appearance for all three controls if they so wish. A discussion about this specific topic can be found here.

Additional context

There's also a perhaps related issue where resource lookup initiated by binding functions does not pick up overriden resources. You can find more info about that here.

Attached files

XamlResourceSystemLookupDemo.zip

@StephenLPeters
Copy link
Contributor

StephenLPeters commented Jul 15, 2020

@MikeHillberg and @kikisaints FYI. I know we have discussed this area in the past. The major concern here is perf.

@StephenLPeters StephenLPeters added team-Framework area-Resources needs-triage Issue needs to be triaged by the area owners and removed needs-triage Issue needs to be triaged by the area owners labels Jul 15, 2020
@chrisglein
Copy link
Member

Yep, this is a huge point of confusion with the existing resource system. There are some performance reasons why it is the way it is, but the confusion in my opinion greatly outweighs that. Fundamentally it doesn't behave the way that developers expect. I'd love to fix this, even if it means creating a new resource reference type or system and phasing out the old (e.g. x:Bind versus Binding).

@kazo0
Copy link

kazo0 commented Nov 30, 2022

Has there been any discussion surrounding this? Would really make lightweight styling more powerful and useful

@bpulliam bpulliam added team-Markup Issue for the Markup team and removed team-Framework labels Aug 22, 2023
@microsoft-github-policy-service microsoft-github-policy-service bot added the needs-triage Issue needs to be triaged by the area owners label Aug 22, 2023
@bpulliam bpulliam removed the needs-triage Issue needs to be triaged by the area owners label Oct 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Resources feature proposal New feature proposal team-Markup Issue for the Markup team
Projects
None yet
Development

No branches or pull requests

6 participants