2012-06-12 57 views
5

如何將元素的寬度從0移至WPF中的實際寬度?動畫寬度與WPF中的實際寬度?

我嘗試這樣做:

<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> 

如果我改變結合到硬編碼值,如100,則寬度被適當動畫,除了我要綁定到該元件的實際寬度。

如果很重要,MyElement是一個邊框,我將爲選項卡項目設置動畫。

根據記錄,這不工作之一:

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

回答

9

我敢肯定,這是錯誤的許多原因,請隨時告訴我有多少WPF法律我違反了,但..我通過創建我自己的BindableDoubleAnimation解決了同樣的問題。

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();; 
    } 
} 

我現在可以使用To From屬性的綁定。

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

有沒有人得到這個'BindableDoubleAnimation',它位於'ControlTemplate'的'VisualState'中的'Storyboard'內部?對於VisualState中只有一個'BindableDoubleAnimation'並且對「To」值進行硬編碼(比如說「100」)的情況,沒有任何動畫,並且GetCurrentValueCore和CreateInstanceCore都不會被調用。對於我在「To」屬性上使用數據綁定的情況,綁定總是失敗,始終輸出錯誤「Can not find source for binding ...」。即使我逐字逐句嘗試所有內容,也會失敗。 –

+0

...我很想讓這個工作 - 它似乎可能是一個很好的解決方案! –

2

那綁定不能在動畫中使用是一個常見的問題。

一個解決辦法是,你使用具有SourceValue & TargetValue(你可以綁定到任何你想要的,包括ActualWidth)的輔助對象CurrentValue(返回動畫值)和Progress可從0.0進行動畫到100.0。當進度改變時,你只需要計算你可以綁定對象的WidthCurrentValue。它不漂亮,但應該工作。

+0

我不清楚這個答案。你能提供一個代碼示例嗎?你在描述類似@ Andy的解決方案嗎? –

+0

@PhillipScottGivens:Andy的回答總是通過在其上創建一個可綁定層來修改動畫。我的建議是不同的,我建議一箇中介對象,總是使用動畫從'0'到'100'的Progress屬性的動畫(因此動畫不會改變),這個對象通過' CurrentValue'屬性,它返回從它的'SourceValue','TargetValue'和'Progress'計算出的值。 –