WP7 - Using Storyboard defined in Application.Reso

2020-07-10 07:35发布

问题:

In my Application.Resources I have the following Storyboard defined.

<Application.Resources>
  <!--Storyboard animation for fading out a UI element-->
  <Storyboard x:Key="FadeOutAnimation">
    <DoubleAnimation From="1"
                     To="0"
                     Duration="0:0:0.25"
                     Storyboard.TargetProperty="Opacity"
                     AutoReverse="False" />
  </Storyboard>
</Application.Resources>

In code-behind I'm using this to fade out some TextBlocks when the user taps on them.

// Get the storyboard from application resources
Storyboard sb = (Storyboard)App.Current.Resources["FadeOutAnimation"];
// Setup the animation target for fade out
Storyboard.SetTarget( sb.Children.ElementAt( 0 ) as DoubleAnimation, myTextBlock );
// Set the animation completed handler
sb.Completed += ( s, e1 ) => {
  // Stop the Storyboard
  sb.Stop();
  // Hide the TextBlock
  myTextBlock.Visibility = Visibility.Collapsed;
};
// Start the Storyboard
sb.begin();

The question is, do I need to somehow 'unhook' myTextBlock from being the target of the DoubleAnimation?

If yes, how do I do it?

The reason I'm asking is I'm worried about a reference to that TextBlock hanging around until this Storyboard is used again.

Thanks for your help!

回答1:

We don't always have to use Xaml in sliverlight if its getting in our way:-

  public static AnimationHelper
  {
       public static void FadeOutAndCollapse(UIElement target)
       {
           DoubleAnimation da = new DoubleAnimation();
           da.From = 1.0;
           da.To = 0.0;
           da.Duration = TimeSpan.FromSeconds(0.25);
           da.AutoReverse = false;

           StoryBoard.SetTargetProperty(da, new PropertyPath("Opacity"));
           StoryBoard.SetTarget(da, target);

           StoryBoard sb = new StoryBoard();
           sb.Children.Add(da);

           EventHandler eh = null;
           eh = (s, args) =>
           {
                target.Visiblity = Visibility.Collapsed;
                sb.Stop();
                sb.Completed -= eh;
           }
           sb.Completed += eh;

           sb.Begin();
       }
}

With this in place you can fade out and collapse any UI element with:-

AnimationHelper.FadeOutAndCollapse(myTextBox);

I'd been inclined to remove the From = 1.0 to make it more general so that elements that have a lower starting opacity don't suddenly flash to full opacity before disappearing.



回答2:

Don't worry about dangling references to lightweight user interface elements; they will be garbage collected when there are no more references. Your more pressing problem is that a single storyboard is being used for multiple text objects and if they overlap, it will do the wrong thing.

For example, if you start one animation and then start another, then they will both stop at the same time because there is only one storyboard and your handler calls stop. Either associate a separate storyboard with each text element in XAML or create a new storyboard in the code-behind for each animation that you want to do.

Also, if you were to use a single storyboard, you should be careful to remove your completed event handler because currently you will keep accumulating them and old handlers will be called when the storyboard re-completes.