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

DependencyProperties precedences storage is wrong #16356

Open
carldebilly opened this issue Apr 18, 2024 · 1 comment · May be fixed by #15684
Open

DependencyProperties precedences storage is wrong #16356

carldebilly opened this issue Apr 18, 2024 · 1 comment · May be fixed by #15684
Assignees
Labels
difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/breaking-change 💥 Categorizes an issue or PR as requiring a breaking change to be fixed. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification

Comments

@carldebilly
Copy link
Member

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

@carldebilly carldebilly added kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. labels Apr 18, 2024
@Youssef1313
Copy link
Member

Youssef1313 commented Apr 18, 2024

Yup. We're taking this as a breaking change in Uno 6. See #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.

@Youssef1313 Youssef1313 added the kind/breaking-change 💥 Categorizes an issue or PR as requiring a breaking change to be fixed. label Apr 18, 2024
@Youssef1313 Youssef1313 self-assigned this Apr 18, 2024
@Youssef1313 Youssef1313 linked a pull request Apr 18, 2024 that will close this issue
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/breaking-change 💥 Categorizes an issue or PR as requiring a breaking change to be fixed. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants