문제

XAML (예 : 리소스)의 어딘가에 애니메이션을 한 번 정의 한 다음 여러 번 재사용하는 방법이 있습니까? DataTeTemplates에서 독립적으로 Datatrigger를 기반으로 동일한 종류의 애니메이션을 시작 해야하는 독립적 인 브러시가 많이 있습니다. 이제 애니메이션이 스토리 보드를 정의 해야하는 것 같습니다 .TargetName 및 Storyboard.targetProperty. 이것은 재사용 성의 목적을 거의 무너 뜨립니다. 어떻게 든 "이 애니메이션을 사용하여 리소스를 사용하지만 이번에는 다른 요소에 적용하십시오"라고 선언하고 싶습니다.

나에게 이것은 다소 기본적이고 중요하며 필수적인 요청 인 것처럼 보이며 나는 그것이 acemplish에 대해 간단하지 않다는 것이 놀랍습니다. 내가 여기서 뭔가를 놓치고 있습니까?

트리거에도 같은 것이 적용됩니다. 색상 애니메이션을 사용하여 동일한 유형의 상태를 나타내는 다른 시각적 요소가 많이 있다고 가정합니다. 예를 들어 "Active"가 "error"등을 "빨간색"으로 페이드 할 때 녹색으로 페이드로 페이드로 페이드로 페이드로 페이드하십시오. 유형 색상의 속성이 있습니다. 나는 동일한 애니메이션을 재정의하는 것이 얼마나 지루한 지 상상하기 어렵지 않다고 생각합니다. 모든 개발자는 이것을 싫어합니다. 나는 필사적으로 C# 코드를 필요로하지 않는 더 쉬운 솔루션을 찾고 있습니다.

지금까지 내가 생각해 낸 것은 다음과 같습니다.

자원에서 애니메이션을 정의하십시오.

<ColorAnimationUsingKeyFrames x:Key="deactivatingColorAnimation" 
                    Storyboard.TargetProperty="Material.(MaterialGroup.Children)[0].Brush.(SolidColorBrush.Color)"                    
                    FillBehavior="HoldEnd" RepeatBehavior="Forever" AutoReverse="True">
      <ColorAnimationUsingKeyFrames.KeyFrames>
        <LinearColorKeyFrame KeyTime="00:00:00" Value="Gray"/>
        <LinearColorKeyFrame KeyTime="00:00:0.25" Value="Gray"/>
        <LinearColorKeyFrame KeyTime="00:00:0.5" Value="Gray" />
        <LinearColorKeyFrame KeyTime="00:00:0.75" Value="Gray" />
     </ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>

트리거의 스토리 보드에 사용합니다 (각 상태 X에 대해이 수백만 번을 반복하십시오.

<DataTrigger Binding="{Binding SubstrateHolder.State}" Value="Deactivating">
        <DataTrigger.EnterActions>
            <BeginStoryboard x:Name="someStateVisualDeactivatingStoryboard">
                <Storyboard Storyboard.TargetName="someStateVisual">
                    <StaticResource ResourceKey="deactivatingColorAnimation" />
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.EnterActions>
        <DataTrigger.ExitActions>
            <RemoveStoryboard BeginStoryboardName="someStateVisualDeactivatingStoryboard" />
        </DataTrigger.ExitActions>
</DataTrigger>

당신은 모든 zillion datatriggers에 대해 반복적으로 복사하여 붙여 넣어야하는지 쉽게 상상할 수 있습니다.

이 모든 트리거를 한 번 정의하고 다른 상태 비주얼에 적용하는 것이 좋습니다. WPF에서 이와 같은 것이 어떻게 해결됩니까? 팁이 있나요?

도움이 되었습니까?

해결책 2

이 일반적인 문제에 대한 좋은 XAML 전용 솔루션은없는 것 같습니다. 나는 주어진 요소의 모든 애니메이션 동작을 정의하는 내 자신의 첨부 된 속성을 작성하게되었습니다. 이 같은:

<DataTemplate>
   <!-- ...  -->
   <Rectangle Fill="Gray">
     <v:AnimationHelper.Animations>
        <v:StandardColorStateAnimation TargetColorProperty="(Rectangle.Fill).(SolidColorBrush.Color)" TargetStateProperty={Binding State} />
     </v:AnimationHelper.Animations>
   </Rectangle>
<DataTemplate>

나머지 (애니메이션 등 생성)는 코드 비유에서 수행됩니다.

다른 팁

이런 식으로 시도해 보시겠습니까?

  • 모든 현재 제어 템플릿을 보이지 않는 루트 요소 (예 : 테두리 또는 스택 패널로 감 으면 경계 상자가 전체 컨트롤을 커버합니다.
  • 모든 트리거와 애니메이션이 포함 된이 보이지 않는 상자의 스타일 또는 제어 템플릿을 만듭니다.
  • 보이지 않는 상자에 애니메이션이 자의적으로 자의적 속성을 애니메이션하도록하십시오.
  • 모든 다른 컨트롤에 대한 시각적 트리에서는 보이지 않는 루트 요소의 색상 속성에 애니메이션을 만들고자하는 속성을 바인딩하십시오.

이 게시물이 게시 당시이 문제가 약간 죽었다는 것을 알고 있지만, 거의 코드가 거의 필요한 솔루션을 찾았습니다.

당신은 만들 수 있습니다 사용자 정의 속성으로 Usercontrol(그림 8 정도까지 스크롤) 사각형과 애니메이션 및 상태 트리거가 포함되어 있습니다. 이 사용자 컨트롤은 변경 될 때 색상 변경을 유발하는 상태와 같은 공공 속성을 정의합니다.

필요한 유일한 코드는 코드에서 변수를 작성하는 것입니다.

사용자 컨트롤은 XAML 스토리 보드 또는 데이터 트리거를 다시 작성하지 않고 반복해서 재사용 할 수 있습니다.

제일 "XAML "내가 생각할 수있는이 목표를 달성하는 것은 전용을 만드는 것입니다. MarkupExtension 리소스 사전에서 애니메이션을 끌어 내고 필요한 속성을 설정합니다. Storyboard.Target, Storyboard.TargetName 그리고 Storyboard.TargetProperty. 코드-홀드가 필요하지만 일회성 노력입니다. MarkupExtensionS는 함께 사용하도록 설계되었습니다 XAML. 가장 간단한 버전은 다음과 같습니다.

[MarkupExtensionReturnType(typeof(Timeline))]
public class AnimationResourceExtension : StaticResourceExtension
{
    //This property is for convienience so that we
    //don't have to remember to set x:Shared="False"
    //on all animation resources, but have an option
    //to avoid redundant cloning if it is
    public bool IsShared { get; set; } = true;

    public DependencyObject Target { get; set; }

    public string TargetName { get; set; }

    public PropertyPath TargetProperty { get; set; }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (base.ProvideValue(serviceProvider) is Timeline animation)
        {
            //If the animation is shared we shall clone it
            //Checking if it is frozen is optional and we can
            //either clone it or throw an exception
            //(or simply proceed knowing one will be thrown anyway)
            if (IsShared || animation.IsFrozen)
                animation = animation.Clone();
            Storyboard.SetTarget(animation, Target);
            Storyboard.SetTargetName(animation, TargetName);
            Storyboard.SetTargetProperty(animation, TargetProperty);
            return animation;
        }
        else
            throw new XamlException("The referenced resource is not an animation");
    }
}

사용량은 매우 간단합니다.

<FrameworkElement.Resources>
    <DoubleAnimation x:Key="MyAnimation" From="0" To="1" Duration="0:0:1" />
</FrameworkElement.Resources>
(...)
<Storyboard>
    <utils:AnimationResource ResourceKey="MyAnimation" TargetName="SomeElement" TargetProperty="Opacity" />
</Storyboard>

이 솔루션이 될 수있는만큼 간단하다는 것은 그 제한 사항이 있습니다. Binding ...도 아니다 DynamicResource 앞서 언급 한 속성에 대한 확장. 그러나 이것은 달성 할 수 있지만 약간의 노력이 필요합니다. Binding 지원은 매우 간단해야합니다. XamlSetMarkupExtensionAttribute(일부 보일러 플레이트 코드). DynamicResource 지원은 조금 까다 롭고 사용하는 것 외에도 XamlSetMarkupExtensionAttribute 포장이 필요합니다 IServiceProvider 적절한 반환 IProvideValueTarget 구현이지만 여전히 가능합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top