2012-06-12 3 views
5

WPF에서 요소의 너비를 0에서 실제 너비만큼 움직이게하려면 어떻게해야합니까? 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> 

I의 100 같이, 하드 코딩 된 값의 결합 바꾸면

는 그 폭이 적절 I는 요소의 실제 폭에 바인드 할 것을 제외 애니메이션 :

는이 시도.

중요한 경우 MyElement이 경계이며 탭 항목에 애니메이션을 적용합니다. 기록을 위해

이 작동하지 않습니다 중 하나를 바인딩이 애니메이션에서 일반적인 문제입니다 사용할 수 없습니다

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

답변

9

나는이 SO 여러 가지 이유로 잘못 확신하고 얼마나 많은 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();; 
    } 
} 

이제받는 사람 속성에 대한 바인딩을 자유롭게 사용할 수 있습니다.

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

'ControlTemplate'의'VisualState'에있는'Storyboard'의 내부에있는'BindableDoubleAnimation'을 위해 이걸 얻은 사람이 있습니까? 나는'VisualState'에 단 하나'BindableDoubleAnimation'가 나는 값이 "하려면"("100"와 같은 말이) 하드 코딩 경우에, 아무것도 애니메이션 않겠다, 그리고'GetCurrentValueCore'도'도는 CreateInstanceCore' 호출지고 . "To"속성에서 데이터 바인딩을 사용하는 경우 바인딩은 항상 실패합니다. 항상 "바인딩 소스를 찾을 수 없습니다 ..."오류가 출력됩니다. 위의 모든 내용을 그대로 사용해도 실패합니다. –

+0

... 나는 이것을 작동시키는 것을 좋아할 것입니다 - 그것은 훌륭한 해결책이 될 수있는 것처럼 보입니다! –

2

.

한 가지 해결 방법은 당신이 (당신이 ActualWidth을 포함하여, 당신이 원하는대로 결합 할 수있는) SourceValue & TargetValue이있는 도우미 개체를 사용하는 것이 될 것 CurrentValue (애니메이션 값을 반환하는) 0.0에서 애니메이션 할 수있는 Progress ~ 100.0. 진행률이 변경되면 개체의 Width을 바인딩 할 수있는 CurrentValue을 계산하면됩니다. 그것은 꽤 아니지만 작동해야합니다.

+0

나는이 대답에 대해 명확하지 않습니다. 코드 샘플을 제공해 주시겠습니까? 앤디의 해결책과 비슷한 것을 묘사하고 있습니까? –

+0

@PhillipScottGivens : Andy의 대답은 항상 애니메이션 위에 바인딩 가능한 레이어를 만들어 애니메이션을 수정합니다. 내가 제안하는 것은 다르다. 나는 '진행'속성을 '0'에서 '100'으로 애니메이션하는 동일한 애니메이션을 항상 사용하는 중개 객체를 제안하므로 (애니메이션이 변경되지 않음)이 객체는 ' SourceValue','TargetValue' 및'Progress'에서 계산 된 값을 반환하는 CurrentValue 속성입니다. –

관련 문제