unoplatform / uno

Open-source platform for building cross-platform native Mobile, Web, Desktop and Embedded apps quickly. Create rich, C#/XAML, single-codebase apps from any IDE. Hot Reload included! 90m+ NuGet Downloads!!
https://platform.uno
Apache License 2.0
8.93k stars 724 forks source link

Problem with inheritance from base WinUI styles #8035

Open HavenDV opened 2 years ago

HavenDV commented 2 years ago

Current behavior

I and some other users recently ran into a problem when trying to inherit from WinUI default styles: https://github.com/microsoft/microsoft-ui-xaml/issues/6648 While not a bug with Uno, the current Workaround for WinUI is completely unusable in WebAssembly because, as I understand it, Uno starts to initialize each of the included XamlControlsResources. This takes quite a long time and slows down loading and WASM by 10-20 times. At the moment I don't see a solution how to use xaml in WinUI and Uno at the same time without losing access to WinUI styles. Is it possible to add to Uno the ability to initialize only one XamlControlsResources, even if multiple are included?

Expected behavior

No response

How to reproduce it (as minimally and precisely as possible)

No response

Workaround

No response

Works on UWP/WinUI

No response

Environment

Uno.UI / Uno.UI.WebAssembly / Uno.UI.Skia

NuGet package version(s)

4.1.0-dev.724

Affected platforms

WebAssembly

IDE

Visual Studio 2022

IDE version

preview 5

Relevant plugins

No response

Anything else we need to know?

No response

jeromelaban commented 2 years ago

Thanks for the report. Could you be more specific about this issue? You're mentioning both a performance and behavior issue. If you have a specific repro to show, it'll help understand it.

HavenDV commented 2 years ago

I'll try to explain: Right now the behavior when including new ResourceDictionary is different for WinUI 3 project and Uno.

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <ResourceDictionary Source="/Resources/Styles.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
</Application.Resources>

For Uno, everything previously included is available in the internal resource dictionary(Styles.xaml). For WinUI, external ones are not available in the internal resource dictionary. So you have to include them again. Therefore, if you use this code in an Uno project, there is a problem with XamlControlsResources - for complex projects, where styles are located by the name TargetType in separate files, XamlControlsResources can be re-included in them (to use BasedOn) and there will be more than 10 times.

To simulate this problem, just do this:

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
</Application.Resources>

This will significantly slow down the WASM application.

jeromelaban commented 2 years ago

Thanks. To be sure we're talking about the same incorrect behavior, can you create a sample that demonstrates what does not work and attach it here?

HavenDV commented 2 years ago

OK sure. To do this, I need a non-trivial WinUI example project to take as a basis (like a calculator). It will be possible to evaluate the drop in performance and interface friezes.

jeromelaban commented 2 years ago

The performance aspect is one problem, but the fact that you need to include multiple times the resources is another. I'm more interested in seeing the behavior difference for now.

HavenDV commented 2 years ago

Having to include multiple identical resources is most likely just a bug that shows up in WinUI when multiple ResourceDictionaries are used. Should I provide you with a WinUI application with this bug so you can make sure there are no other workarounds? P.S. The behavior of the bug itself is also described here: https://github.com/microsoft/microsoft-ui-xaml/issues/6648 (in case you didn't see it in the initial description).

jeromelaban commented 2 years ago

Got it. Unfortunately, the way resource dictionaries work are causing this type of resolution drawbacks when using styles in App.xaml. You can only reimport the full style that you want to override.

This may change at some point when the XamlControlsResources styles are considered "in-box" styles, where they have precedence over styles merged in the app.xaml Resources.

This is not something we can change at this point, as we do the same WinUI does.

HavenDV commented 2 years ago

You mean that I can only use a specific XamlControlsResources style file instead of using the entire XamlControlsResources. How to do it? And is it possible to get around the problem of a drastic performance drop when using multiple XamlControlsResources in the Uno itself? Use singleton instance?

jeromelaban commented 2 years ago

You'll need to copy the original WinUI/UWP style, and modify it. Note that WinUI/UWP also has a performance drop when integrating dictionaries multiple times, particularly at runtime when resolving resources.

jeromelaban commented 2 years ago

Note that we've made changes to the way resources are created, and the inclusion of XamlControlsResources should be faster starting from Uno 4.1.