2016-12-05 1 views
0

код, чтобы увидеть, что происходит:DoubleAnimation с помощью VisualTreeHelper работает только один раз

XAML файл:

<!-- put this code into your page xaml code--> 

<Page.Resources> 
    <Style x:Name="opabuttonstyle" TargetType="Button"> 
     <Setter Property="Margin" Value="10" /> 
     <Setter Property="HorizontalAlignment" Value="Center" /> 
     <Setter Property="VerticalAlignment" Value="Center" /> 
    </Style> 
</Page.Resources> 

<Grid Background="{StaticResource BackgroundGradient-Blue}"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Grid Grid.Row="0" HorizontalAlignment="Center"> 
     <Button 
      x:Name="testingIsTheFutureButton" 
      Grid.Row="0" 
      Grid.Column="0" 
      Click="testingIsTheFutureButton_Click" 
      Content="Opacity Animation" 
      Style="{StaticResource opabuttonstyle}" /> 
    </Grid> 
    <Grid Grid.Row="1"> 
     <StackPanel x:Name="stackingStackPanel" HorizontalAlignment="Center"> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
      <TextBlock Text="Element" /> 
     </StackPanel> 
    </Grid> 
</Grid> 

файл класса SingleAnimations.cs:

// This function takes UIElement and DoubleAnimate it to fade in. 
public static void SimpleElementFadeIn(object sender, int fadeTime, int delay) 
{ 
     UIElement element = sender as UIElement; //bierz element 
     Storyboard storyboard = new Storyboard(); 
     DoubleAnimation doubleAnimation = new DoubleAnimation(); 
     doubleAnimation.BeginTime = new TimeSpan(0, 0, 0, 0, delay); 
     doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, fadeTime)); 
     doubleAnimation.From = 0; 
     doubleAnimation.To = 1; 
     Storyboard.SetTarget(doubleAnimation, element); 
     Storyboard.SetTargetProperty(doubleAnimation, "Opacity"); 
     storyboard.Children.Add(doubleAnimation); 
     storyboard.Begin(); 
} 

CollectionAnimations.cs файл класса:

// This function goes through every children element in UIElement (grid, 
//stackpanel or whatever we send there) and animates it using previous function 
public static void OpacityWithChildren_Light(object sender, int delay) 
{ 
    SetOpacityToZero_Deep(sender); // set opacity to 0 to all elements before animation 
    UIElement rootElement = sender as UIElement; 
    int childCount= VisualTreeHelper.GetChildrenCount(rootElement); 
    if (childCount > 0) 
    { 
     for (int index = 0; index < childCount; index++) 
     { 
       UIElement element = (UIElement)VisualTreeHelper.GetChild(rootElement, index); 
       SingleAnimations.SimpleElementFadeIn(element, 100, delay * index); 
     } 
    } 
} 

// This function goes through every children element like the funtion above 
// and sets opacity of these elements to 0 (so every element is invisible before it's animated) 
public static void SetOpacityToZero_Deep(object sender) 
{ 
    UIElement rootElement = sender as UIElement; 
    int childNumber = VisualTreeHelper.GetChildrenCount(rootElement); 
    if (childNumber > 0) 
    { 
     for (int index = 0; index < childNumber; index++) 
     { 
      UIElement element = (UIElement)VisualTreeHelper.GetChild(rootElement, index); 
       element.Opacity = 0; 
     } 
    } 
} 

Для того, чтобы начать анимацию я называю

CollectionAnimations.OpacityWithChildren_Light(stackingStackPanel, 50); 

в button_click события.

Что я ожидаю, что все TextBlocks в StackPanel исчезают и собираются исчезать один за другим. Это происходит, но только при первом использовании. Если я снова нажму кнопку, то все они будут видны и будут анимированы один за другим - не то, что я хочу. Если я вернусь к MainPage и снова введите страницу, она будет работать снова (один раз), как раньше.

Должно быть, я должен очистить что-то вроде cashe. Я не встречал ничего подобного в документации или просто пропустил это. Ничего подобного не упоминалось для независимых анимаций. Я испортил этот код, пробуя разные вещи и подходы, но ничего не получилось.

+0

Это всего лишь комментарий, почему бы не переместить 'element.Opacity = 0;' в цикл foreach 'OpacityWithChildren_Light'? –

+0

@JeroenvanLangen UIElement будет мгновенно анимирован, и я хочу, чтобы все они были невидимыми, а затем отображались. –

ответ

1

Я предлагаю вам использовать две раскадровки, чтобы установить Opacity на 0, а другой - на DoubleAnimation, как вы хотите.

Поэтому нам не нужно устанавливать Opacity в 0 на UIElement.Opacity. Когда Storyboard множества Opacity до нуля будет завершен, мы должны быть в состоянии начать Storyboard Пад в

. Например:

Класс SingleAnimation:

internal class SingleAnimations 
{ 
    public static DoubleAnimation SetToZero(object sender) 
    { 
     var element = sender as UIElement; 
     DoubleAnimation doubleAnimation = new DoubleAnimation(); 
     doubleAnimation.BeginTime = new TimeSpan(0, 0, 0, 0, 0); 
     doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 0)); 
     doubleAnimation.From = 1; 
     doubleAnimation.To = 0; 
     Storyboard.SetTarget(doubleAnimation, element); 
     Storyboard.SetTargetProperty(doubleAnimation, "Opacity"); 
     return doubleAnimation; 

    } 

    public static DoubleAnimation SimpleElementFadeIn(object sender, int fadeTime, int delay) 
    { 
     var element = sender as UIElement; 
     DoubleAnimation doubleAnimation = new DoubleAnimation(); 
     doubleAnimation.BeginTime = new TimeSpan(0, 0, 0, 0, delay); 
     doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, fadeTime)); 
     doubleAnimation.From = 0; 
     doubleAnimation.To = 1; 
     Storyboard.SetTarget(doubleAnimation, element); 
     Storyboard.SetTargetProperty(doubleAnimation, "Opacity"); 
     return doubleAnimation; 

    } 

Метод OpacityWithChildren_Light:

public static void OpacityWithChildren_Light(object sender, int delay) 
{ 
    var storyboardOfSetOpacityToZero = new Storyboard(); 
    var storyboardFadeIn = new Storyboard(); 
    UIElement rootElement = sender as UIElement; 
    int childCount = VisualTreeHelper.GetChildrenCount(rootElement); 
    if (childCount > 0) 
    { 
     for (int index = 0; index < childCount; index++) 
     { 
      UIElement element = (UIElement)VisualTreeHelper.GetChild(rootElement, index); 
      var SetOpacityToZero = SingleAnimations.SetToZero(element); 
      var SetOpacityToOne = SingleAnimations.SimpleElementFadeIn(element, 100, delay * index); 
      storyboardOfSetOpacityToZero.Children.Add(SetOpacityToZero); 
      storyboardFadeIn.Children.Add(SetOpacityToOne); 
     } 
     storyboardOfSetOpacityToZero.Begin(); 
     storyboardOfSetOpacityToZero.Completed += (s, e) => { storyboardFadeIn.Begin(); }; 
    } 
} 
+0

Спасибо! Этот код намного лучше, чем мой, а также работает как шарм :) Тем не менее интересно, почему Opacity нужно анимировать, чтобы он был установлен в 0 и не работает другим способом. –