2012-06-12 17 views
5

Bir öğenin genişliğini WPF'de 0'dan gerçek genişliğine nasıl canlı yapabilirim? WPF'deki gerçek genişlik için animasyon genişliği?

<ControlTemplate.Triggers> 
    <EventTrigger RoutedEvent="Loaded"> 
     <BeginStoryboard> 
      <Storyboard> 
       <DoubleAnimation Duration="0:0:0.3" To="{Binding ElementName=MyElement, Path=ActualWidth}" From="0" Storyboard.TargetProperty="Width" Storyboard.TargetName="MyElement" /> 
      </Storyboard> 
     </BeginStoryboard> 
    </EventTrigger> 
</ControlTemplate.Triggers> 

Ben 100 gibi sabit kodlanmış bir değere bağlanması değiştirirseniz

ardından genişliği düzgün ben elemanın gerçek genişliğine bağlama istediğinizde haricinde animasyon:

Bu çalıştı.

Önemli ise, MyElement bir kenarlıktır ve bir sekme öğesini hareketlendiriyorum. Kayıt için

, bu işe yaramazsa ya: bağlamaları animasyonlar ortak sorunu olduğunu kullanılamaz O

To="{Binding RelativeSource={RelativeSource AncestorType={x:Type Border}}, Path=ActualWidth}" 

cevap

9

Eminim bu bir çok nedenden dolayı yanlıştır ve kaç tane WPF yasalarının ihlal edildiğini bildirmekten çekinmeyin. Kendi BindableDoubleAnimation'ı oluşturarak aynı sorunu çözdüm.

public class BindableDoubleAnimation : DoubleAnimationBase 
{ 
    DoubleAnimation internalAnimation; 

    public DoubleAnimation InternalAnimation { get { return internalAnimation; } } 

    public double To 
    { 
     get { return (double)GetValue(ToProperty); } 
     set { SetValue(ToProperty, value); } 
    } 

    /// <summary> 
    /// Dependency backing property for the <see cref="To"/> property. 
    /// </summary> 
    public static readonly DependencyProperty ToProperty = 
     DependencyProperty.Register("To", typeof(double), typeof(BindableDoubleAnimation), new UIPropertyMetadata(0d, new PropertyChangedCallback((s, e) => 
      { 
       BindableDoubleAnimation sender = (BindableDoubleAnimation)s; 
       sender.internalAnimation.To = (double)e.NewValue; 
      }))); 


    public double From 
    { 
     get { return (double)GetValue(FromProperty); } 
     set { SetValue(FromProperty, value); } 
    } 

    /// <summary> 
    /// Dependency backing property for the <see cref="From"/> property. 
    /// </summary> 
    public static readonly DependencyProperty FromProperty = 
     DependencyProperty.Register("From", typeof(double), typeof(BindableDoubleAnimation), new UIPropertyMetadata(0d, new PropertyChangedCallback((s, e) => 
     { 
      BindableDoubleAnimation sender = (BindableDoubleAnimation)s; 
      sender.internalAnimation.From = (double)e.NewValue; 
     }))); 


    public BindableDoubleAnimation() 
    { 
     internalAnimation = new DoubleAnimation(); 
    } 

    protected override double GetCurrentValueCore(double defaultOriginValue, double defaultDestinationValue, AnimationClock animationClock) 
    { 
     return internalAnimation.GetCurrentValue(defaultOriginValue, defaultDestinationValue, animationClock); 
    } 

    protected override Freezable CreateInstanceCore() 
    { 
     return internalAnimation.Clone();; 
    } 
} 

Şu anda To From özelliklerinde bağlama kullanmakta serbestim.

<local:BindableDoubleAnimation Storyboard.TargetProperty="Width" From="0" To="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Window}}"/> 
+0

Bunu “ControlTemplate” ın bir “VisualState” inin içinde bulunan 'Storyboard'un içinde bulunan 'BindableDoubleAnimation' için çalışmak için bunu yapan var mı? VisualState'de sadece bir "BindableDoubleAnimation" var ve "To" değerini ("100" gibi bir şey söylemek için) kodladığım durumlarda hiçbir şey canlandırılmaz ve ne "GetCurrentValueCore" ne de "CreateInstanceCore" adı verilir . "Kime" özelliği üzerinde veri bağlama kullandığım durumlarda, her zaman bağlanma başarısız olur, her zaman hata "Çıktı için kaynak bulamıyor ..." çıktı. Herşeyi yukarıdaki sözüstümden denediğimde bile başarısız olur. –

+0

... Bunu işe almak isterim - bu harika bir çözüm olabilirmiş gibi görünüyor! –

2

.

Bir geçici çözüm (eğer ActualWidth dahil istediğini bağlamak olabilir) SourceValue & TargetValue olan bir yardımcı nesnesi kullanabilirsiniz olurdu bir CurrentValue (animasyonlu değer döndürür olan) ve 0.0 ile hareketli olabilir bir Progress 100.0'a. İlerleme değiştiğinde, nesnenizin Width'unu bağlayabileceğiniz CurrentValue değerini hesaplamanız gerekir. Güzel değil ama işe yaramalı.

+0

Bu yanıtta açık değilim. Bir kod örneği verebilir misiniz? @ Andy'nin çözümüne benzer bir şeyi mi açıklıyorsunuz? –

+0

@PhillipScottGivens: Andy'nin cevabı, her zaman üstünde bir çiftlenebilir katman oluşturarak animasyonu değiştirir. Önerdiğim şey farklıdır, her zaman "İlerleme" özelliğini "0" dan "100" e dönüştüren aynı animasyonu kullanan bir aracı nesne öneririm (böylece animasyon değişmez), bu nesne bir "SourceValue", "TargetValue" ve "Progress" değerlerinden hesaplanan değeri döndüren CurrentValue özelliği. –

İlgili konular