diff --git a/src/Uno.UI/FeatureConfiguration.cs b/src/Uno.UI/FeatureConfiguration.cs
index 78bb824b5d20..76fbdf4cd5c2 100644
--- a/src/Uno.UI/FeatureConfiguration.cs
+++ b/src/Uno.UI/FeatureConfiguration.cs
@@ -493,6 +493,16 @@ public static class UIElement
#endif
}
+ public static class VisualState
+ {
+ ///
+ /// When this is set, the will be applied synchronously when changing state,
+ /// unlike UWP which waits the for the end of the (if any) to apply them.
+ ///
+ /// This flag is for backward compatibility with old versions of uno and should not be turned on.
+ public static bool ApplySettersBeforeTransition { get; set; } = false;
+ }
+
public static class WebView
{
#if __ANDROID__
diff --git a/src/Uno.UI/UI/Xaml/Media/Animation/Storyboard.cs b/src/Uno.UI/UI/Xaml/Media/Animation/Storyboard.cs
index 479f473a279f..bddfc74bf732 100644
--- a/src/Uno.UI/UI/Xaml/Media/Animation/Storyboard.cs
+++ b/src/Uno.UI/UI/Xaml/Media/Animation/Storyboard.cs
@@ -287,6 +287,7 @@ internal void TurnOverAnimationsTo(Storyboard storyboard)
((ITimeline)child).Stop();
}
}
+
State = TimelineState.Stopped;
}
diff --git a/src/Uno.UI/UI/Xaml/Media/Animation/Timeline.cs b/src/Uno.UI/UI/Xaml/Media/Animation/Timeline.cs
index 08ae4a815a63..3de91c724dd1 100644
--- a/src/Uno.UI/UI/Xaml/Media/Animation/Timeline.cs
+++ b/src/Uno.UI/UI/Xaml/Media/Animation/Timeline.cs
@@ -24,7 +24,7 @@ public Timeline()
State = TimelineState.Stopped;
}
- protected enum TimelineState
+ protected internal enum TimelineState
{
Active,
Filling,
@@ -46,7 +46,7 @@ protected string[] GetTraceProperties()
/// An internally-used property which is essentially equivalent to , except that it
/// distinguishes from .
///
- protected TimelineState State { get; set; }
+ protected internal TimelineState State { get; set; }
public TimeSpan? BeginTime
{
diff --git a/src/Uno.UI/UI/Xaml/VisualStateGroup.cs b/src/Uno.UI/UI/Xaml/VisualStateGroup.cs
index ee06acd3b2ed..4b0266ac803f 100644
--- a/src/Uno.UI/UI/Xaml/VisualStateGroup.cs
+++ b/src/Uno.UI/UI/Xaml/VisualStateGroup.cs
@@ -30,6 +30,11 @@ public sealed partial class VisualStateGroup : DependencyObject
/// The xaml scope in force at the time the VisualStateGroup was created.
///
private readonly XamlScope _xamlScope;
+ private (VisualState state, VisualTransition transition) _current;
+
+ public event VisualStateChangedEventHandler CurrentStateChanging;
+
+ public event VisualStateChangedEventHandler CurrentStateChanged;
public VisualStateGroup()
{
@@ -41,6 +46,8 @@ public VisualStateGroup()
this.RegisterParentChangedCallback(this, OnParentChanged);
}
+ public VisualState CurrentState => _current.state;
+
public string Name { get; set; }
#region States Dependency Property
@@ -67,7 +74,6 @@ public IList States
internal set { this.SetValue(StatesProperty, value); }
}
- // Using a DependencyProperty as the backing store for States. This enables animation, styling, binding, etc...
public static DependencyProperty StatesProperty { get; } =
DependencyProperty.Register(
"States",
@@ -101,16 +107,13 @@ public IList Transitions
internal set { this.SetValue(TransitionsProperty, value); }
}
- // Using a DependencyProperty as the backing store for Transitions. This enables animation, styling, binding, etc...
public static DependencyProperty TransitionsProperty { get; } =
DependencyProperty.Register(
"Transitions",
typeof(IList),
typeof(VisualStateGroup),
new FrameworkPropertyMetadata(
- defaultValue: null,
- propertyChangedCallback: (s, e) => ((VisualStateGroup)s)?.OnTransitionsChanged(e)
- )
+ defaultValue: null)
);
#endregion
@@ -137,17 +140,11 @@ private void VisualStateChanged(object sender, IVectorChangedEventArgs e)
RefreshStateTriggers();
}
- //Adds Event Handlers when collections changed
- private void OnTransitionsChanged(DependencyPropertyChangedEventArgs e)
+ private void OnParentChanged(object instance, object key, DependencyObjectParentChangedEventArgs args)
{
+ RefreshStateTriggers(force: true);
}
- public VisualState CurrentState { get; internal set; }
-
- public event VisualStateChangedEventHandler CurrentStateChanging;
-
- public event VisualStateChangedEventHandler CurrentStateChanged;
-
internal void RaiseCurrentStateChanging(VisualState oldState, VisualState newState)
{
if (this.CurrentStateChanging == null)
@@ -175,80 +172,60 @@ private Control FindFirstAncestorControl()
return (this.GetParent() as FrameworkElement)?.FindFirstParent();
}
- internal void GoToState(IFrameworkElement element, VisualState state, VisualState originalState, bool useTransitions, Action onStateChanged)
+ internal void GoToState(
+ IFrameworkElement element,
+ VisualState state,
+ bool useTransitions,
+ Action onStateChanged)
{
+ global::System.Diagnostics.Debug.Assert(state is null || States.Contains(state));
+
if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
{
this.Log().DebugFormat("Go to state [{0}/{1}] on [{2}]", Name, state?.Name, element);
}
- var transition = FindTransition(originalState?.Name, state?.Name);
-
- EventHandler