2016-06-14 9 views
0

화살표 그림 (png)에 간단한 애니메이션을 실행하고 싶습니다. 화살표는 아래쪽 또는 위쪽을 가리키며 애니메이션은 화살표가 가리키는 방향으로 화살표를 통과하는 파도라고 가정합니다.WPF에서 스타일을 변경하면 스토리 보드가 변경되지 않습니다.

Image 컨트롤을 사용하고 두 가지 스타일 중 하나를 지정합니다. 이 스타일은 스토리 보드에서 사용할 그림과 세 개의 이중 애니메이션을 정의합니다. 애니메이션은 영원히 이미지가 생성 된 순간부터 무조건 실행되어야합니다. 스타일 중 하나는 위쪽으로 움직이는 물결이 위로 향하는 화살표 (Trend_Rising)이고 다른 스타일은 아래쪽으로가는 물결이 아래쪽으로 향하는 화살표입니다 (Trend_Falling).

다음은 이미지이며 스타일은 이미지가 포함 된 UserControl에서 참조되는 별도의 파일에 있습니다.

<Image x:Name="TrendImg" Style="{DynamicResource Trend_Falling}" /> 

이는 스타일 파일의 내용이다 :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 

    <Style x:Key="Trend_Base" TargetType="Image"> 

     <Setter Property="OpacityMask"> 
      <Setter.Value> 
       <LinearGradientBrush StartPoint="0,1" EndPoint="0,0"> 
        <GradientStop Color="Black" /> 
        <GradientStop Color="Transparent" /> 
        <GradientStop Color="Black" /> 
       </LinearGradientBrush> 
      </Setter.Value> 
     </Setter> 

    </Style> 

    <Style x:Key="Trend_Rising_Base" TargetType="Image" BasedOn="{StaticResource Trend_Base}"> 

     <Style.Triggers> 
      <Trigger Property="IsVisible" Value="True"> 
       <Trigger.EnterActions> 
        <BeginStoryboard> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[0].Offset" From="-0.1" To="0.9" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[1].Offset" From="0.0" To="1.0" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[2].Offset" From="0.1" To="1.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 
      </Trigger> 
     </Style.Triggers> 

    </Style> 

    <Style x:Key="Trend_Falling_Base" TargetType="Image" BasedOn="{StaticResource Trend_Base}"> 

     <Style.Triggers> 
      <Trigger Property="IsVisible" Value="True"> 
       <Trigger.EnterActions> 
        <BeginStoryboard> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[0].Offset" From="0.9" To="-0.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[1].Offset" From="1.0" To="0.0" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[2].Offset" From="1.1" To="0.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 
      </Trigger> 
     </Style.Triggers> 

    </Style> 

    <Style x:Key="Trend_Rising" TargetType="Image" BasedOn="{StaticResource Trend_Rising_Base}"> 
     <Setter Property="Height" Value="16" /> 
     <Setter Property="Source" Value="trend_rising.png" /> 
    </Style> 

    <Style x:Key="Trend_Falling" TargetType="Image" BasedOn="{StaticResource Trend_Falling_Base}"> 
     <Setter Property="Height" Value="16" /> 
     <Setter Property="Source" Value="trend_falling.png" /> 
    </Style> 

</ResourceDictionary> 

것은 내가 프로그래밍 스타일을 변경하면, 애니메이션이 변경되지 않는다는 것입니다. 예를 들어 응용 프로그램을 시작하면 (이미지에 Trend_Falling 스타일이 할당 됨) 아래쪽 화살표가 아래쪽으로 움직이는 파동 애니메이션과 함께 표시됩니다. 그러나 런타임에 스타일을 Trend_Rising으로 변경하면 화살표 그림이 변경되지만 애니메이션은 그대로 유지됩니다.

TrendImg.SetResourceReference(Control.StyleProperty, "Trend_Rising") 

내가 뭘 잘못하고 있니? 어떤 도움을 주셔서 감사합니다. 고맙습니다!

- 편집 -

나는 이미지의 후손 인 ImageWithAnim 클래스를 생성하고, 여기에 부울 애니메이션 종속성 속성을 추가했다. 그런 다음 IsVisible 대신 해당 속성에 트리거를 연결했습니다. True이면 스토리 보드가 시작되고 false로 설정하면 멈추게됩니다. 설정하면 애니메이크이 거짓이되며 RisingStoryboard 이름을 System.Windows에서 확인할 수 없다는 예외가 발생합니다. .Style. 이 예제가 작동해야하는 StackOverflow에 대한 여러 게시물을 발견했습니다.

그래서 ... 지금 어떻게해야 제대로 할 수 있는지 알 수 없습니다. 어떤 도움을 주셔서 감사합니다. 고맙습니다!

이 변경된 XAML입니다 :

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Test="clr-namespace:StyleChangeTest"> 

    <Style x:Key="Trend_Base" TargetType="Test:ImageWithAnim"> 

     <Setter Property="OpacityMask"> 
      <Setter.Value> 
       <LinearGradientBrush StartPoint="0,1" EndPoint="0,0"> 
        <GradientStop Color="Black" /> 
        <GradientStop Color="Transparent" /> 
        <GradientStop Color="Black" /> 
       </LinearGradientBrush> 
      </Setter.Value> 
     </Setter> 

    </Style> 

    <Style x:Key="Trend_Rising_Base" TargetType="Test:ImageWithAnim" BasedOn="{StaticResource Trend_Base}"> 

     <Style.Triggers> 
      <Trigger Property="Animate" Value="True"> 
       <Trigger.EnterActions> 
        <BeginStoryboard x:Name="RisingStoryboard"> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[0].Offset" From="-0.1" To="0.9" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[1].Offset" From="0.0" To="1.0" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[2].Offset" From="0.1" To="1.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 
      </Trigger> 

      <Trigger Property="Animate" Value="False"> 
       <Trigger.EnterActions> 
        <StopStoryboard BeginStoryboardName="RisingStoryboard" /> 
       </Trigger.EnterActions> 
      </Trigger> 
     </Style.Triggers> 

    </Style> 

    <Style x:Key="Trend_Falling_Base" TargetType="Test:ImageWithAnim" BasedOn="{StaticResource Trend_Base}"> 

     <Style.Triggers> 
      <Trigger Property="Animate" Value="True"> 
       <Trigger.EnterActions> 
        <BeginStoryboard x:Name="FallingStoryboard"> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[0].Offset" From="0.9" To="-0.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[1].Offset" From="1.0" To="0.0" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[2].Offset" From="1.1" To="0.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 
      </Trigger> 

      <Trigger Property="Animate" Value="False"> 
       <Trigger.EnterActions> 
        <StopStoryboard BeginStoryboardName="FallingStoryboard" /> 
       </Trigger.EnterActions> 
      </Trigger>     
     </Style.Triggers> 

    </Style> 

    <Style x:Key="Trend_Rising" TargetType="Test:ImageWithAnim" BasedOn="{StaticResource Trend_Rising_Base}"> 
     <Setter Property="Height" Value="16" /> 
     <Setter Property="Source" Value="trend_rising.png" /> 
    </Style> 

    <Style x:Key="Trend_Falling" TargetType="Test:ImageWithAnim" BasedOn="{StaticResource Trend_Falling_Base}"> 
     <Setter Property="Height" Value="16" /> 
     <Setter Property="Source" Value="trend_falling.png" /> 
    </Style> 

</ResourceDictionary> 

그리고 여기 ImageWithAnim 클래스의 : 우연의 일치

Public Class ImageWithAnim 
    Inherits Image 

    Private Shared _animate As DependencyProperty = DependencyProperty.Register("Animate", 
                       GetType(Boolean), 
                       GetType(ImageWithAnim), 
                       New PropertyMetadata(defaultValue:=False)) 

    Public Shared ReadOnly Property AnimateProperty As DependencyProperty 
     Get 
      Return _animate 
     End Get 
    End Property 

    Public Property Animate() As Boolean 
     Get 
      Return CBool(GetValue(_animate)) 
     End Get 
     Set(value As Boolean) 
      SetValue(_animate, value) 
     End Set 
    End Property 

End Class 
+0

당신은 단지 이미지 대상 유형을 타겟팅하고 있습니다. 따라서 이미지 자체가 바뀌 었는지 상관하지 않습니다. 단지 이미지 만 있습니다. 이 경로로 이동하여 이미지 소스를 변경하면 별도의 애니메이션 사이에서 수동으로 스왑/스왑을 시작해야합니다. –

+0

감사합니다, @ChrisW.하지만 어떤 식으로 애니메이션을 멈추고 다시 시작 하시겠습니까? 어느 정도 WPF를 알고 있지만 전문가는 아닙니다. 스타일을 사용하는 간단한 방법으로 수행 할 수 있습니까? 또는 프로그래밍 방식으로 수행해야합니까? 내 마음에 떠오르는 첫 번째 아이디어는 애니메이션 시작 또는 중지 여부를 결정하는 속성이있는 Image 클래스 자손을 만드는 것입니다. 그런 다음 Image 대신 해당 클래스를 사용하고 IsVisible 대신 해당 속성에 트리거를 연결하십시오. 좋은 생각입니까 아니면 모두 더 간단하게 할 수 있습니까? –

+0

부울 Animate 종속성 속성을 가진 Image의 자손을 만들었습니다. IsVisible 대신 스타일로 사용했고 Animate를 True로 설정하여 애니메이션을 시작했습니다. 그러나 Animate를 False로 설정하여 중지하면 작동하지 않습니다. 그래서 Animate = False에 연결된 두 번째 트리거를 추가했습니다. StopStoryboard 요소에는 BeginStoryBoardName이 x : Animate = True로 정의 된 BeginStoryboard의 이름으로 설정되었습니다. 이제 Animate를 False로 설정할 때마다 System.Windows.Style 네임 스페이스에서 지정된 BeginStoryboard 이름을 확인할 수 없다는 예외가 발생합니다. 나는 붙어있다. –

답변

0

난 그냥 내 자신의 질문에 대한 답을 발견했다. 스토리 보드의 이름은 기본 스타일로 정의 되었기 때문에 해결할 수 없습니다.두 가지 관심 분야에서 직접 정의한 경우 애니메이션 속성 인 ImageWithAnim을 예외없이 사용하여 시작하고 중지 할 수있었습니다.

이미지의 스타일을 변경 때, 나는 다음을 수행해야합니다 :

TrendImg.Animate = False 
TrendImg.SetResourceReference(ImageWithAnim.StyleProperty, "Trend_Falling") 
TrendImg.Animate = True 

지금 애니메이션이 제대로 변경 및 방향 파도 애니메이션 이동 화살표 포인트 인 것입니다 내가 성취하기를 원하는 것.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:Test="clr-namespace:StyleChangeTest"> 

    <Style x:Key="Trend_Base" TargetType="Test:ImageWithAnim"> 

     <Setter Property="OpacityMask"> 
      <Setter.Value> 
       <LinearGradientBrush StartPoint="0,1" EndPoint="0,0"> 
        <GradientStop Color="Black" /> 
        <GradientStop Color="Transparent" /> 
        <GradientStop Color="Black" /> 
       </LinearGradientBrush> 
      </Setter.Value> 
     </Setter> 

    </Style> 

    <Style x:Key="Trend_Rising" TargetType="Test:ImageWithAnim" BasedOn="{StaticResource Trend_Base}"> 
     <Setter Property="Height" Value="16" /> 
     <Setter Property="Source" Value="trend_rising.png" /> 

     <Style.Triggers> 
      <Trigger Property="Animate" Value="True"> 
       <Trigger.EnterActions> 
        <BeginStoryboard x:Name="RisingStoryboard"> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[0].Offset" From="-0.1" To="0.9" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[1].Offset" From="0.0" To="1.0" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[2].Offset" From="0.1" To="1.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 

       <Trigger.ExitActions> 
        <StopStoryboard BeginStoryboardName="RisingStoryboard" /> 
       </Trigger.ExitActions> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

    <Style x:Key="Trend_Falling" TargetType="Test:ImageWithAnim" BasedOn="{StaticResource Trend_Base}"> 
     <Setter Property="Height" Value="16" /> 
     <Setter Property="Source" Value="trend_falling.png" /> 

     <Style.Triggers> 
      <Trigger Property="Animate" Value="True"> 
       <Trigger.EnterActions> 
        <BeginStoryboard x:Name="FallingStoryboard"> 
         <Storyboard> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[0].Offset" From="0.9" To="-0.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[1].Offset" From="1.0" To="0.0" Duration="0:0:2" RepeatBehavior="Forever" /> 
          <DoubleAnimation Storyboard.TargetProperty="OpacityMask.GradientStops[2].Offset" From="1.1" To="0.1" Duration="0:0:2" RepeatBehavior="Forever" /> 
         </Storyboard> 
        </BeginStoryboard> 
       </Trigger.EnterActions> 

       <Trigger.ExitActions> 
        <StopStoryboard BeginStoryboardName="FallingStoryboard" /> 
       </Trigger.ExitActions> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

</ResourceDictionary> 

내가 처음에 기본 스타일에서 스토리 보드를 넣어 이유를 설명하기 :

그리고 여기에 변경된 스타일입니다. 문제는 원래의 응용 프로그램에서 여러 개의 화살표 그림이 있고 스토리 보드 정의를 반복하지 않으려 고한다는 것입니다. 그러나 그것은해야 할 것 같습니다.