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.89k stars 720 forks source link

`DependencyProperties` precedences storage is wrong #16356

Open carldebilly opened 6 months ago

carldebilly commented 6 months ago

Current behavior

The current precedences mechanism is not following its own logic, especially when applying values coming from default style (defined in generic.xaml), implicit style (keyless resolved through resource dictionaries) and explicit style (keyed style referenced directly on the element).

TLDR

The default style is always saved under the ImplicitStyle precedence and the applied style (implicit or explicit) is saved under the ExplicitStyle precedence.

Observed result

Building the following code:

public sealed partial class MyControl : Control
{
    // Register a DependencyProperty "MyProperty" of type string
    public static readonly DependencyProperty MyPropertyProperty
        = DependencyProperty.Register("MyProperty", typeof(string), typeof(MyControl), new PropertyMetadata("Default Metadata Value")
    );

    public string MyProperty
    {
        get => (string)GetValue(MyPropertyProperty);
        set => SetValue(MyPropertyProperty, value);
    }

    public MyControl()
    {
        DefaultStyleKey = typeof(MyControl);

        MyProperty = "Local Value";
    }
}

In generic.xaml:

  <Style TargetType="local:MyControl">
    <Setter Property="MyProperty" Value="Default from Generic.xaml" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="local:MyControl">
            <TextBlock Text="{TemplateBinding MyProperty}" />
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

In app.xaml (AppResources.xaml)

  <Style TargetType="local:MyControl" x:Key="MyControlStyle">
    <Setter Property="MyProperty" Value="Explicit Style Value" />
  </Style>

  <Style TargetType="local:MyControl" x:Key="MyControlImplicitStyle">
    <Setter Property="MyProperty" Value="Implicit Style Value" />
  </Style>

  <Style TargetType="local:MyControl" BasedOn="{StaticResource MyControlImplicitStyle}" />

Used like that in the MainPage.xaml:

  <StackPanel
        HorizontalAlignment="Left"
        VerticalAlignment="Center"
        Padding="100, 20"
        Spacing="20">

    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup x:Name="CommonStates">
        <VisualState x:Name="NormalState" />
        <VisualState x:Name="AlteredState">
          <Storyboard>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="my" Storyboard.TargetProperty="MyProperty">
              <DiscreteObjectKeyFrame KeyTime="0" Value="Value from VisualStateManager" />
            </ObjectAnimationUsingKeyFrames>
          </Storyboard>
        </VisualState>
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <local:MyControl x:Name="my" MyProperty="XAML Value (explicit)" Style="{StaticResource MyControlStyle}" />
    <TextBlock x:Name="result"></TextBlock>
  </StackPanel>

Observed Result

Precedence Observed Value
Coercion (unset)
FillingAnimations (unset)
Animations Value from VisualStateManager
Local XAML Value (explicit)
TemplatedParent (unset)
ExplicitStyle Explicit Style Value
ImplicitStyle Default from Generic.xaml
Inheritance (unset)
DefaultStyle (unset)
DefaultValue Default Metadata Value

Expected behavior

Expected Result

Precedence Observed Value
Coercion (unset)
FillingAnimations (unset)
Animations Value from VisualStateManager
Local XAML Value (explicit)
TemplatedParent (unset)
ExplicitStyle Explicit Style Value
ImplicitStyle Implicit Style Value (!!)
Inheritance (unset)
DefaultStyle Default from Generic.xaml (!!)
DefaultValue Default Metadata Value

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

No response

Workaround

No response

Works on UWP/WinUI

No

Environment

Uno.WinUI / Uno.WinUI.WebAssembly / Uno.WinUI.Skia

NuGet package version(s)

Uno 5.1

Affected platforms

WebAssembly, Android, iOS, macOS (AppKit), Mac Catalyst, Skia (WPF), Skia (GTK on Linux/macOS/Windows), Skia (Linux Framebuffer)

IDE

No response

IDE version

No response

Relevant plugins

No response

Anything else we need to know?

No response

Youssef1313 commented 6 months ago

Yup. We're taking this as a breaking change in Uno 6. See https://github.com/unoplatform/uno/pull/15684

There shouldn't be any bugs caused by this though. Just wrong terminology being used.

Note that the precedences enum isn't intended for public access, even if it's public.