uno
uno copied to clipboard
`VisualState` `Setter` value precedence is too high
Current behavior
Currently when a VisualState
in a VisualStateGroup
is applied, its Setters
are applied with Animations
precedence. This seems different from UWP, where the set value can be then overwritten by manually setting the property in code.
Expected behavior
Local
should be used.
How to reproduce it (as minimally and precisely as possible)
Workaround
Environment
Nuget Package:
- [x] Uno.UI / Uno.UI.WebAssembly / Uno.UI.Skia
- [ ] Uno.WinUI / Uno.WinUI.WebAssembly / Uno.WinUI.Skia
- [ ] Uno.SourceGenerationTasks
- [ ] Uno.UI.RemoteControl / Uno.WinUI.RemoteControl
- [ ] Other:
Nuget Package Version(s):
Affected platform(s):
- [x] iOS
- [x] Android
- [x] WebAssembly
- [x] WebAssembly renderers for Xamarin.Forms
- [x] macOS
- [x] Skia
- [x] WPF
- [x] GTK (Linux)
- [x] Tizen
- [x] Windows
- [ ] Build tasks
- [ ] Solution Templates
IDE:
- [ ] Visual Studio 2017 (version: )
- [x] Visual Studio 2019 (version: )
- [ ] Visual Studio for Mac (version: )
- [ ] Rider Windows (version: )
- [ ] Rider macOS (version: )
- [ ] Visual Studio Code (version: )
This is unlikely to be a case of swapping one 'wrong' precedence for the 'right' one unfortunately. Uno's and UWP's precedence handling are just different. Uno's DependencyProperty system is heavily based off of WPF's; UWP's DP system is a streamlined and simplified version of the WPF system, which gives the same result most of the time, but differs in edge cases like this one and https://github.com/unoplatform/uno/issues/3443.
@davidjohnoliver It seems it will be a bit more tricky, as the original value returns once the custom state is unapplied. So it does behave partially as a "stack", but not completely, as changing the local value overwrites the setter.
I agree with @davidjohnoliver we have to review our precedence system. This is also linked to https://github.com/unoplatform/uno/issues/631 and https://github.com/unoplatform/uno/issues/3739
Closed #5171 as the solution I attempted there was not adequate.
My findings from WinUI source code:
We should have a flag IsLocalValueNewerThanAnimationsValue
The flag by default is false. Then:
- When we set or clear a value for Animations, set the flag to false.
- When we set a value for Local, set the flag to true.
- When we set a value for non-Local non-Animations, set it to false (it doesn't make much sense to me, but that's what I'm seeing in WinUI code)
- When getting a DP value, if the highest precedence is Animations and
IsLocalValueNewerThanAnimationsValue
is true, we return the Local value.
For 3, this is the part of the code I'm referring to:
There should still be a missing part here, because if we clear Local value, we should set the flag to false. Not sure where this happens in WinUI code.