question

AriaRad-9889 avatar image
0 Votes"
AriaRad-9889 asked AriaRad-9889 answered

[UWP] Animating elements when they become Visible

Hello,

I would like to have a page element (typically a stackpanel or a grid) be animated when it is made visible. These elements can be toggled visible or collapsed with a button and this can be done repeatedly. The problem is that while using a ContentThemeTransition or EntranceThemeTransition gives a decent animation, these transitions only play once where I want them to play every time the element becomes visible.

So I thought about making a custom animation that affects the Y offset and the opacity. But I don't know how I can make it so that every time the element's Visibility changes to Visible the animation starts playing. I tried to Trigger the animation when the element becomes Visible, but couldn't figure out how to do it (with StateTriggers). Is this how it should be done and if so how?
Is it possible to have this behaviour be handled by the XAML code entirely? Also, is it possible to make said code into its own style so we can put it into a resource dictionary for the app for re-use?
I've been messing around in Blend with some sample code:

 <StackPanel Orientation="Vertical">
            
         <Button x:Name="test" Click="test_Click" Content="Animate" Margin="24"/>
         <StackPanel Orientation="Vertical" x:Name="targetstackpanel" 
                                 Margin="24,0,0,0"
                                 Visibility="Visible" RenderTransformOrigin="0.5,0.5">
             <StackPanel.RenderTransform>
                 <CompositeTransform/>
             </StackPanel.RenderTransform>
             <VisualStateManager.VisualStateGroups>
                 <VisualStateGroup x:Name="VisualStateGroup">
                     <VisualStateGroup.Transitions>
                         <VisualTransition GeneratedDuration="00:00:00" To="Appearing">
                             <VisualTransition.GeneratedEasingFunction>
                                 <ExponentialEase EasingMode="EaseOut"/>
                             </VisualTransition.GeneratedEasingFunction>
                             <Storyboard>
                                 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="targetstackpanel" Storyboard.TargetProperty="(UIElement.Opacity)">
                                     <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                                     <EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
                                 </DoubleAnimationUsingKeyFrames>
                                 <DoubleAnimationUsingKeyFrames Storyboard.TargetName="targetstackpanel" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
                                     <EasingDoubleKeyFrame KeyTime="00:00:00" Value="-25"/>
                                     <EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="0"/>
                                 </DoubleAnimationUsingKeyFrames>
                             </Storyboard>
                         </VisualTransition>
                     </VisualStateGroup.Transitions>
                     <VisualState x:Name="CollapsedPanel"/>
                     <VisualState x:Name="Appearing"></VisualState>
                 </VisualStateGroup>
             </VisualStateManager.VisualStateGroups>
    
             <StackPanel Orientation="Vertical" Margin="0,6">
                 <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                                        FontWeight="Bold" TextWrapping="Wrap">
                     Header1
                 </TextBlock>
                 <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                                        TextWrapping="Wrap" Margin="12,0,0,0">
                     - Lorem ipsum dolor sit amet, consectetur adipiscing elit.
                     <LineBreak/>- Phasellus ultricies turpis
                     <LineBreak/>- sit amet turpis accumsan, vel placerat
                     <LineBreak/>- nisi elementum.
                     <LineBreak/>- Quisque aliquam ante non lorem varius, 
                     at porta urna bibendum. 
                     <LineBreak/>- Vestibulum lacinia vulputate nunc vel rutrum. 
                     Aliquam ac lobortis dolor. Donec blandit ante sed sem 
                     varius posuere.
                     <LineBreak/>- Aliquam fringilla mauris condimentum, 
                     consequat lectus id, elementum lacus.
                     <LineBreak/>- Duis mollis fermentum laoreet.
                     <LineBreak/>- Nam in leo orci.
                 </TextBlock>
             </StackPanel>
             <StackPanel Orientation="Vertical" Margin="0,6">
                 <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                                        FontWeight="Bold" TextWrapping="Wrap">
                     Header2
                 </TextBlock>
                 <TextBlock Style="{StaticResource BodyTextBlockStyle}"
                                        TextWrapping="Wrap" Margin="12,0,0,0">
                                 - Vivamus nisl sem,
                                 <LineBreak/>- ornare eget sodales quis
                 </TextBlock>
             </StackPanel>
             <Button Content="Some button" 
                                 x:Name="btn" HorizontalAlignment="Stretch"/>
         </StackPanel>
    
     </StackPanel>

The code-behind looks something like this:

 private void test_Click(object sender, RoutedEventArgs e)
         {
             if (targetstackpanel.Visibility == Windows.UI.Xaml.Visibility.Collapsed)
             {
                 targetstackpanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
             }
             else
             {
                 targetstackpanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
             }
         }





windows-uwp
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I'm not sure if I understand you correctly. You want to make targetstackpanel visible first. The targetstackpanel shows in somewhere and then you want to move the targetstackpanel to a place you want using animation. Is that right?

0 Votes 0 ·

This is pretty much correct, yes. So when the targetstackpanel is in its collapsed state and is made Visible, it should fade in while slightly moving down (or up, I can tweak the specifics later). This looks similar to the animation from EntranceThemeTransition if you check it in the WinUI 3 demo. That's what I was trying to achieve.
So I was thinking that the the XAML code needs some sort of trigger that plays the animation, and this trigger should be activated when the targetstackpanel goes into its Visible state. Not sure if this is possible, but that's what I had in mind.

0 Votes 0 ·
RoyLi-MSFT avatar image
0 Votes"
RoyLi-MSFT answered

Hello,

Welcome to Microsoft Q&A!

You could try to use DataTriggerBehavior and GoToStateAction from XAML Behaviors SDK to get your target.

Here is a simple sample that I made

     <Page.Resources>
         <Storyboard x:Name="myAnimation">
             <DoubleAnimationUsingKeyFrames Storyboard.TargetName="targetstackpanel" Storyboard.TargetProperty="(UIElement.Opacity)">
                 <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
                 <EasingDoubleKeyFrame KeyTime="00:00:05" Value="1"/>
             </DoubleAnimationUsingKeyFrames>
             <DoubleAnimationUsingKeyFrames Storyboard.TargetName="targetstackpanel" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
                 <EasingDoubleKeyFrame KeyTime="00:00:00" Value="-25"/>
                 <EasingDoubleKeyFrame KeyTime="00:00:05" Value="0"/>
             </DoubleAnimationUsingKeyFrames>
         </Storyboard>
     </Page.Resources>
    
     <Grid x:Name="RootGrid">
         <Button Content="Click" Click="Button_Click"/>
            
         <StackPanel x:Name="targetstackpanel" Background="Aqua" Width="200" Visibility="Collapsed"   Height="200" Margin="24,0,0,0">
             <StackPanel.RenderTransform>
                 <CompositeTransform />
             </StackPanel.RenderTransform>
             <TextBlock Text="This is a Text" Foreground="BlueViolet"/>
         </StackPanel>
         <Interactivity:Interaction.Behaviors>
             <Core:DataTriggerBehavior Binding="{Binding Visibility, ElementName=targetstackpanel}" Value="Visible">
                 <Core:CallMethodAction TargetObject="{Binding}" MethodName="StartAnimation"/>
             </Core:DataTriggerBehavior>
         </Interactivity:Interaction.Behaviors>
     </Grid>


Code-behind:

 public MainPage()
         {
             this.InitializeComponent();
             this.DataContext = this;
         }
    
         private void Button_Click(object sender, RoutedEventArgs e)
         {
             targetstackpanel.Visibility = Visibility.Visible;
               
         }
    
         public void StartAnimation()
         {
             myAnimation.Begin();
         }


Thank you.


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.





5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

AriaRad-9889 avatar image
0 Votes"
AriaRad-9889 answered

Thanks a lot! That works.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.