2009-09-23 26 views
7

Tôi đang làm thay đổi kích thước đường viền trong Silverlight tuy nhiên tôi cũng cần phải dần dần loại bỏ phần lề xung quanh nó (hiện tại là 50). Pha trộn dường như không tạo ra một sự thay đổi về lợi nhuận - nó chỉ nhảy từ 50 đến 0 trong một lần. Có cách nào để đạt được điều này?Animate Margin Change in Silverlight

Trả lời

8

Vấn đề là Margin thực sự thuộc loại "System.Windows.Thickness" không phải là đối tượng phụ thuộc, do đó, Trái, Trên, Phải và Dưới là KHÔNG Thuộc tính phụ thuộc và do đó không thể hoạt ảnh bằng DoubleAnimation (cho phép tweening).

Điều được sử dụng để tạo hoạt ảnh cho Ký tự là một ObjectAnimation không được làm tròn. Đây là lý do tại sao bạn thấy nhảy từ vị trí ban đầu đến vị trí mới của nó. Như một ví dụ phổ biến khác, điều tương tự cũng xảy ra khi bạn cố gắng tạo hiệu ứng thuộc tính Hiển thị giữa Hiển thị và Thu gọn.

Bạn có thể cần phải thực hiện hoạt ảnh dựa trên hẹn giờ để tạo hiệu ứng lề hoặc triển khai loại Hoạt ảnh của riêng bạn cho đối tượng Độ dày.

0

Here is an updated version cho phép bạn tạo hoạt động từ bên trong 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); 
     } 
    } 
} 

Và sau đó bạn có thể làm điều này trong 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"/> 

Lưu ý rằng nếu bạn không đặt thuộc tính Target thành DoubleAnimation trong XAML, bạn sẽ không thể hiển thị control/page trong Blend. Để khắc phục điều này, chỉ cần thêm thuộc tính mục tiêu giả (trong mã ở trên tôi đã thêm thuộc tính độ mờ là giá trị gấp đôi), và nó sẽ được ghi đè lên khi chạy anyway

+0

Tôi đã cố gắng sử dụng tính năng này trong XAML theo ví dụ và tôi nhận được một luồng lỗi trong SL5. Tôi đã thêm một khai báo 'xmlns: someName', nhưng có vẻ như XAML không biết thuộc tính' someName: ThicknessAnimationX' là gì. – Shaamaan