XamlFlair / XamlFlair

XamlFlair is an animation library for UWP, WPF, and Uno, built to facilitate Xaml animations using only attached properties.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

WPF StartWith Problem

Charles808 opened this issue · comments

I tested below code in WPF.

<Rectangle xf:Animations.Primary="{xf:Animate BasedOn={StaticResource ScaleFromBottom}, Delay=5000, Event=Visibility}"
           xf:Animations.StartWith="{StaticResource ScaleFromBottom}" />

Then I added 2 buttons,
one (Hide) to make the element Visibility == Collapsed,
and the other button (Show) to make the element Visibility == Visible.

The element is initially Collapsed in the XAML.
When I clicked "Show" Button, it works perfectly.
Then, I clicked "Hide" Button. It is collapsed as expected.

But, after I clicked the "Show" for the 2nd time.
The element is visible directly, and only after the Delay, the animation is start working ?

Am I missing something ?

@Charles808

I would like to debug this issue. Can you attach a simple project with this scenario? Thanks.

@Charles808

After re-reading your post, unfortunately yes the behavior is expected. Visibility is a special event, in fact it's not an actual event that exists on a FrameworkElement, but a property that is being observed:

var isVisible = element.Visibility == Visibility.Visible;

The animation will only trigger when the Visibility = Visible. In your case this is working correctly, however the scaling will not be repeated. Therefore the 1st time you click Show, it was scale from the bottom. Then when you click Hide, the button will hide, BUT it does NOT scale back down. Then when you click Show again, it won't scale because it already is scaled.

Unfortunately there is no way to use a Secondary animation on a Visibility = Collapsed. To solve your issue you would need to use a CombinedBinding to trigger a Primary and Secondary animation:

<Button xf:Animations.CombinedBinding="{Binding IsChecked, ElementName=SampleCheckBox}"
		xf:Animations.Primary="{xf:Animate BasedOn={StaticResource FadeIn}, Event=None}"
		xf:Animations.Secondary="{xf:Animate BasedOn={StaticResource FadeOut}, Event=None}"
		xf:Animations.StartWith="{StaticResource FadeOut}" />

Hi,

Thank you very much for the reply.
And sorry for the late reply. My hand are currently tied with several projects.

For the moment, I have to make the Delay parameter to zero, as a workaround for this.
At least, it makes the UI less weird for the animation. Although, this means I can't take advantage of the delay feature benefit.

I will try to do your suggestion and tested it later on.

Thank you once again, I will close this case for the moment.

@Charles808 , I've decided to re-open this issue and make sure that a bug doesn't exist. I based my answer off what I remember, but I want to verify it in code as soon as I can. I will keep you posted. But definitely a CombinedBinding usually helps in certain scenarios.

@Charles808 , so I've made myself a sample and reproduced it. And yes it's exactly what I mentioned. So the 2nd time around, since the Scale value did not return back to its original value (by using a Secondary animation) , it simply appears suddenly. The property is then animated after the delay. Just wanted to confirm that is the intended behavior because XamlFlair will not set values to prepare an animation, it simply runs a Storyboard with the values supplied. And of course, StartWith will only execute on Loaded (therefore once in your case). I hope this clears things up.

Hi @XamlFlair , feel free to open this case if you think that is needed.

Thank you very much for your updates.

Hmm, I'm kinda lost here.
Please correct me if I'm wrong.

First you said "the Scale value did not return back to its original value (by using a Secondary animation)" and then you also said that is the intended behavior. I understand that far.
But, I thought this is what the "StartWith" are used for, to force it to a specified original value.
Because if not, then what is the "StartWith" real benefit ?
If "StartWith will only execute on Loaded", then actually even without it the animation are run just fine on Loaded event.
At this stage, I don't find any use of the "StartWith".

Hi @Charles808 ,

StartWith is handy when using a Delay. Suppose you FadeIn an element after 5 seconds, initially the element will be visible for 5 seconds and then suddenly FadeOut to animate the FadeIn. Using StartWith can help by initially setting a FadeOut on Load. However if that animation is run a second time, the StartWith is not used.

In other words, StartWith is EXACTLY the same as setting a RenderTransform directly in your Xaml.

if (startSettings != null)
{
elem.ApplyInitialSettings((AnimationSettings)startSettings);
}

element.RenderTransform = transform;

Sorry for any confusions I may have caused.

Hi @XamlFlair ,

Thank you very much for your great explanation !
I appreciated it !