-
Notifications
You must be signed in to change notification settings - Fork 759
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
Uno Doesn't Find Styles in Themes\Generic.xaml #4424
Comments
@davidjohnoliver Is this an easy one to add support for? It will help a lot of apps coming over from UWP and seems pretty important it should work right out of the box. If you can provide a general idea of where to modify code I can look at this as well. |
@robloo This is going to be a long answer :p First of all, there might be a partial solution which addresses the bug you encountered (which might be the most pressing issue in real-world cases): detect if there's a The full problemFirst, about styles from The 'explicit style' is whatever is explicitly set to the Take the following: <Page.Resources>
<Style TargetType="Button">
<Setter Property="Background"
Value="Fuchsia" />
</Style>
</Page.Resources>
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock Text="Hello, world!"
Margin="20"
FontSize="30" />
<Button Content="Implicit style" />
<Button Content="Explicit style">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground"
Value="ForestGreen" />
</Style>
</Button.Style>
</Button>
</StackPanel> We're defining an 'implicit style' for The main thing I don't fully understand, and needs to be assessed to handle By 'all possible cases' I mean that
The Essentially it needs to be understood, for all combinations of type definition/style declaration/usage, whether the declared style is treated as a 'default style' or an 'implicit style'. For now Uno takes the position that a 'default style' can only be declared in the same assembly where a control is declared, but that might too simplistic, it needs to be fully investigated. Relevant Uno codeCurrently in Uno, default style registrations are generated by XamlCodeGeneration. Note that there's a subtlety that Implicit styles are resolved here. As far as testing, there are some tests already here, and Uno.UI.Tests.ViewLibrary is set up to be able to test how code and Xaml coming from a class library is treated. |
@davidjohnoliver Thanks for the response :) I'll have to read through it in more detail later. A few quick comments though:
My understanding is what is in Themes/Generic.xaml is the default style. The location itself is the differentiator. This is why it is a magic location similar to the Strings folder. Any styles here should be at the bottom of the precedence though and can be overridden anywhere downstream. Style precedence is simply whichever is closest to the control in the following order:
|
@davidjohnoliver Another property recently came to my attention I've never used before: Control.DefaultStyleResourceUri. So it seems to make sense that Generic.xaml should be used for the default style unless overridden by this property. Does any of this make sense? |
Interesting! I'd never noticed that property before. Certainly seems like a piece of the puzzle.
Except that it isn't simple in practice. The thing is that saying "Style A takes precedence over Style B" is too vague, because it could mean:
WinUI's style resolution rules combine both types of precedence, as my markup example above was trying to illustrate. |
@davidjohnoliver Yes, I understood your point :) I guess I also confused things by talking about a few different concepts at once. Let me start by just talking about default styles and then talk about each one individually. I believe Uno does not correctly handle default styles. It would also explain the confusion of when to consider a style default or implicit. Default Style The base style that is ALWAYS applied to a control. This may then be merged (as the base) with any implicit or explicit style later on. WPF, and then UWP, very much use a 'magic' location of However, of course this location can be modified in the assembly information as well. At least in WPF it was possible to modify AssemblyInfo.cs: This default style location can also be modified at the control-level (as opposed to the assembly-level) using the Control.DefaultStyleResourceUri property in UWP mentioned above. Implicit Style Any style just using TargetType is implicit. This will be applied ON TOP of the default style as you said. Searching for implicit styles is done as I mentioned before a few comments ago, minus Generic.xaml which is likely only for default or explicit styles.
Note that an implicit style is only applied on top of the default style once. You only have to merge styles once here assuming there is no BasedOn property value.
Explicit Style Any style that is used directly in a control by specifying the style key or setting the Control.Style property. Note that explicit styles may be defined anywhere:
Explicit styles will override any implicit style but not the default style (as you stated). They will be merged on top of the default style.
Other
I'm probably missing a few cases but I'm quite sure a style resolution algorithm as described above would work to solve everything we've discussed. |
@robloo Excellent summary :)
What would be a great first step would be some tests that shed some light on how |
This makes sense to me. I believe UWP ignores any "implicit" styles within Generic.xaml because, well, there are no implicit styles supported there. They can't be as there would be no way to differentiate them from default styles. Only the default styles are defined within Generic.xaml but any styles there may also have a key and be used explicitly later on. Also, in a standard UWP solution, adding a new TemplatedControl will add Themes/Generic.xaml automatically and create the default style there for you. All templated controls within a UWP app or controls library search for the default styles there and pull them in automatically. I first noticed this issue for custom controls that were not getting their default style applied by Uno -- I was never putting implicit or explicit styles in Generic.xaml. |
I was able to make Themes\Generic.xaml work from a multi-targeted class library (containing some custom controls) for Android and WinUI3. The Project structure is given below in case this helps others: <Project Sdk="MSBuild.Sdk.Extras/3.0.23">
<PropertyGroup>
<TargetFrameworks>MonoAndroid10.0;net5.0-windows10.0.19041.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition=" $(TargetFramework.Contains('windows')) ">
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
<DefineConstants>WINDOWS_WINUI3;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Uno.WinUI" Version="3.8.13" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.Contains('windows')) ">
<PackageReference Include="Microsoft.ProjectReunion" Version="0.8.1" />
<PackageReference Include="Microsoft.ProjectReunion.Foundation" Version="0.8.1" />
<PackageReference Include="Microsoft.ProjectReunion.WinUI" Version="0.8.1" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.Contains('windows')) == 'false'">
<Page Include="Themes\Generic.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
</Project> I found that Generic.xaml does not work from a shared source project for non-Windows platforms. It has to be packaged in a class library as shown above. |
@Youssef1313 can this be addressed for single project now? |
To find WinUI's approach, search for "themes/generic.xaml" in WinUI 3 sources |
@jeromelaban, @MartinZikmund, @Youssef1313 regarding this issue, based on what was shared recently here #18157 (comment), can this be addressed easily lately? And the priority of doing it needs to be reviewed lately? |
As a workaround Generic.xaml can be moved to another folder (e.g. Styles) and then add Generic.Xaml to the global merged dictionaries in App.xaml. I tested it on WASM, Desktop and Windows. |
Current behavior
Any styles defined in
Themes\Generic.xaml
are not found.Expected behavior
This is the standard location for default styles in UWP apps and needs to be supported. It is also common practice to use MergedDictionary to pull in resources from other directories referenced by
Generic.xaml
.When Uno searched for an implicit/default style for any TemplatedControl defined in
Generic.xaml
it should be found.How to reproduce it (as minimally and precisely as possible)
As described.
Workaround
Define styles in App.xaml. Uno correctly handles nested MergedDictionaries so the following works:
Environment
Nuget Package Version(s): 3.1.6
Affected platform(s):
IDE:
Relevant plugins:
Anything else we need to know?
The text was updated successfully, but these errors were encountered: