2009-09-23 4 views
7

Я обновляю размер рамки в Silverlight, но мне также необходимо постепенно удалить маржу вокруг нее (в настоящее время 50). Blend, похоже, не генерирует анимацию изменения маржи - она ​​просто прыгает с 50 на 0 за один раз. Есть ли способ достичь этого?Изменение размера анимации в Silverlight

ответ

8

Проблема заключается в том, что Margin действительно имеет тип «System.Windows.Thickness», который НЕ является объектом зависимостей, таким образом, Left, Top, Right и Bottom НЕ являются зависимыми свойствами и поэтому не могут быть анимированы с использованием DoubleAnimation (который допускает твинирование).

Что используется для анимации маржи, является ObjectAnimation, которая не движется. Вот почему вы видите, что маржа переходит из исходного местоположения в новое место. В качестве еще одного распространенного примера это происходит, когда вы пытаетесь анимировать свойство видимости между Visible и Collapsed.

Вам нужно либо выполнить анимацию на основе таймера, чтобы анимировать маржу, либо реализовать свой собственный тип анимации для объектов Толщины.

0

Here is an updated version, что позволяет анимировать из в XAML

using System; 
using System.Net; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Ink; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 

namespace NiceCards.Animations 
{ 
    public class ThicknessAnimationX 
    { 
     public static readonly DependencyProperty ElementProperty = DependencyProperty.RegisterAttached("Element", typeof(DependencyObject), typeof(DoubleAnimation), new PropertyMetadata(new PropertyChangedCallback(OnElementPropertyChanged))); 

     // The time along the animation from 0-1 
     public static DependencyProperty TimeProperty = DependencyProperty.RegisterAttached("Time", typeof(double), typeof(DoubleAnimation), new PropertyMetadata(OnTimeChanged)); 

     // The object being animated 
     public static DependencyProperty TargetProperty = DependencyProperty.RegisterAttached("Target", typeof(DependencyObject), typeof(ThicknessAnimationX), null); 
     public static DependencyProperty TargetPropertyProperty = DependencyProperty.RegisterAttached("TargetProperty", typeof(DependencyProperty), typeof(DependencyObject), null); 

     public static readonly DependencyProperty FromProperty = DependencyProperty.RegisterAttached("From", typeof(Thickness), typeof(DoubleAnimation), null); 
     public static readonly DependencyProperty ToProperty = DependencyProperty.RegisterAttached("To", typeof(Thickness), typeof(DoubleAnimation), null); 

     public static void SetElement(DependencyObject o, DependencyObject value) 
     { 
      o.SetValue(ElementProperty, value); 
     } 

     public static DependencyObject GetElement(DependencyObject o) 
     { 
      return (DependencyObject)o.GetValue(ElementProperty); 
     } 

     private static void OnElementPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      if (e.NewValue != null) 
      { 
       DoubleAnimation doubleAnimation = (DoubleAnimation)d; 

       doubleAnimation.SetValue(TargetProperty, e.NewValue); 
       doubleAnimation.From = 0; 
       doubleAnimation.To = 1; 
       doubleAnimation.SetValue(TargetPropertyProperty, FrameworkElement.MarginProperty); 
       Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(ThicknessAnimationX.Time)")); 
       Storyboard.SetTarget(doubleAnimation, doubleAnimation); 
      } 
     } 


     private static void OnTimeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
     { 
      DoubleAnimation animation = (DoubleAnimation)sender; 
      double time = GetTime(animation); 
      Thickness from = (Thickness)sender.GetValue(FromProperty); 
      Thickness to = (Thickness)sender.GetValue(ToProperty); 
      DependencyProperty targetProperty = (DependencyProperty)sender.GetValue(TargetPropertyProperty); 
      DependencyObject target = (DependencyObject)sender.GetValue(TargetProperty); 
      target.SetValue(targetProperty, new Thickness((to.Left - from.Left) * time + from.Left, 
                  (to.Top - from.Top) * time + from.Top, 
                  (to.Right - from.Right) * time + from.Right, 
                  (to.Bottom - from.Bottom) * time + from.Bottom)); 
     } 

     public static double GetTime(DoubleAnimation animation) 
     { 
      return (double)animation.GetValue(TimeProperty); 
     } 

     public static void SetTime(DoubleAnimation animation, double value) 
     { 
      animation.SetValue(TimeProperty, value); 
     } 

     public static Thickness GetFrom(DoubleAnimation animation) 
     { 
      return (Thickness)animation.GetValue(FromProperty); 
     } 

     public static void SetFrom(DoubleAnimation animation, Thickness value) 
     { 
      animation.SetValue(FromProperty, value); 
     } 

     public static Thickness GetTo(DoubleAnimation animation) 
     { 
      return (Thickness)animation.GetValue(ToProperty); 
     } 

     public static void SetTo(DoubleAnimation animation, Thickness value) 
     { 
      animation.SetValue(ToProperty, value); 
     } 
    } 
} 

И тогда вы можете сделать это в XAML

<VisualStateManager.VisualStateGroups> 
    <VisualStateGroup x:Name="Positions"> 
     <VisualStateGroup.Transitions> 
      <VisualTransition GeneratedDuration="0:0:0.2"/> 
     </VisualStateGroup.Transitions> 
     <VisualState x:Name="Left">      
      <Storyboard> 
       <DoubleAnimation Duration="0:0:0.3" NiceCards:ThicknessAnimationX.To="0,0,0,0" NiceCards:ThicknessAnimationX.Element="{Binding ElementName=rectangle1}" Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="Opacity"/> 
      </Storyboard>      
     </VisualState> 
     <VisualState x:Name="Right">      
      <Storyboard> 
       <DoubleAnimation Duration="0:0:0.3" NiceCards:ThicknessAnimationX.To="0,200,0,0" NiceCards:ThicknessAnimationX.Element="{Binding ElementName=rectangle1}" Storyboard.TargetName="rectangle1" Storyboard.TargetProperty="Opacity"/> 
      </Storyboard>      
     </VisualState> 
    </VisualStateGroup> 
</VisualStateManager.VisualStateGroups> 
<Rectangle Height="100" HorizontalAlignment="Left" Margin="23,25,0,0" x:Name="rectangle1" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="200" Fill="#FF1BAA00"/> 

Обратите внимание, что если вы не устанавливаете свойство Target в DoubleAnimation в XAML, вы не сможете отобразить элемент управления/страницу в Blend. Чтобы исправить это, просто добавьте фальшивое целевое свойство (в приведенном выше коде я добавил свойство непрозрачности, которое является двойным значением). И все равно он будет переопределен во время выполнения.

+0

Я попытался использовать это в XAML в соответствии с вашим пример, и я получаю поток ошибок в SL5. Я добавил объявление 'xmlns: someName', но, похоже, XAML не знает, что такое свойство someName: ThicknessAnimationX. – Shaamaan

Смежные вопросы