Frage

Gibt es eine Möglichkeit, eine Animation irgendwo in XAML zu definieren (z. B. als Ressource) einmal und dann mehrmals wiederverwendet werden? Ich habe eine Menge von unabhängigen Bürsten über differnt Datatemplates, die unabhängig voneinander die gleiche Art von Animation auf einem Datatrigger Basis starten müssen. Jetzt, da es scheint, dass eine Animation ein Storyboard.TargetName und Storyboard.TargetProperty zu definieren hat. Dieser ziemlich besiegt den Zweck der Wiederverwertbarkeit. Ich möchte irgendwie erklären „verwenden diese Animation die Ressource bilden, sondern es auf ein anderes Element dieses Mal anwenden“.

Für mich scheint eine eher einfach, wichtige und wesentliche Anforderung zu sein und ich bin überrascht, dass es nicht, dass gerade nach vorne zu erledige. Bin ich etwas fehlt hier?

Das gleiche gilt für Trigger. Angenommen, ich habe eine Menge Differnt visueller Elemente, die alle die gleiche Art von Zustand mit Farbanimationen darstellen. Z.B. verblassen zu grün, wenn „aktiv“ fade in „rot“, wenn „Fehlern“ usw. Der einzige Unterschied zwischen der Visuals ist ihre Form / visuelle Struktur des gewünschte Animation Verhalten ist das gleiche, sie alle irgendwo in ihrer visuellen Struktur ein Element haben, das hat eine Eigenschaft des Typs Farbe. Ich denke, es ist nicht schwer sich vorzustellen, wie mühsam es ist, die gleichen Animationen und Datatrigger Sätze immer und immer wieder neu zu definieren. Jeder Entwickler hasst diese. Ich suche verzweifelt nach einer einfacheren Lösung, die nicht keine (oder zumindest sehr wenig) c # -Code hinter erfordert.

Was habe ich mit so weit kommen, ist dies:

Definieren Sie die Animationen in einer Ressource lik diese (wiederholen dies für alle Grundzustände, dass es, wie die Aktivierung, aktiv, inaktiv, Fehler):

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

Die Verwendung es in Storyboard den Auslösern (Wiederholen Sie diese zig Millionen Mal für jeden Zustand X jeden Differnt stateviusal, stets mit einem neuen Namen für das Storyboard kommen):

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

Sie können sich leicht vorstellen, wie viel aufblasen XAML ich wiederholt haben zu kopieren und für alle, die zig DataTriggers einfügen.

Es wäre cool sein, alle zu definieren diese einmal löst und es zu verschiedenen staatlichen Visuals anzuwenden. Wie ist dies etwas wie in WPF gelöst? Jede Spitze?

War es hilfreich?

Lösung 2

Es scheint keine gute XAML-only Lösung dieses allgemeinen Problems zu sein. Ich beendete meine angefügten Eigenschaften bis zu schreiben, die alle Animationsverhalten für ein bestimmtes Element zu definieren. So etwas wie folgt aus:

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

Der Rest (die Erstellung der Animation usw.) in dem Code-Behind getan.

Andere Tipps

Könnten Sie so etwas wie dies versuchen?

  • Wickeln Sie alle aktuellen Steuerungsschablonen mit einem unsichtbaren Wurzelelement, z.B. Eine Grenze oder ein Stackpanel, Box, deren Begrenzungs die gesamte Steuerung abdecken.
  • Erstellen Sie einen Stil oder Steuer Vorlage für diese unsichtbare Box, die alle Ihre Trigger und Animationen enthält.
  • Haben Sie die Animationen eine beliebige Farbe Eigenschaft auf der unsichtbaren Feld animieren.
  • In der bildenden Bäume für alle Ihre verschiedenen Kontrollen, binden alle Eigenschaften, die Sie in die Color-Eigenschaft auf der unsichtbaren Wurzelelement animieren möchten.

Ich weiß, das Thema auf dem Zeitpunkt dieser Veröffentlichung ein bisschen tot ist, aber ich habe eine Lösung finden, die sie hinter sehr wenig Code erforderlich ist.

Sie können eine Usercontrol mit benutzerdefinierten Eigenschaften (nach unten scrollen bis etwa 8), die das Rechteck sowie die Animationen und Zustands Trigger enthält. Diese Benutzerkontrolle würde eine öffentliche Eigenschaft wie Status definieren, die die Farbänderung auslösen würden, wenn geändert.

Die einzige Code-Behind benötigt, um Ihre Variablen im Code zu erstellen.

Die Steuer Anwender kann sie über wiederverwendet werden und immer wieder, ohne die die XAML Storyboards zu Umschreiben oder Daten auslöst.

Die „ XAML Art und Weise“ Um dieses Ziel zu erreichen, ich denken kann, ist gewidmet MarkupExtension zu schaffen, die die Animation aus dem Ressource-Wörterbuch ziehen würde und notwendige Eigenschaften eingestellt - ich nehme an denjenigen einen begrenzt Teilmenge von Storyboard.Target, Storyboard.TargetName und Storyboard.TargetProperty. Obwohl es einige Code-behind erfordert, ist es eine einmalige Aufwand, außerdem werden MarkupExtensions entworfen mit XAML verwendet werden. Hier ist die einfachste Version:

[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");
    }
}

Die Benutzung ist sehr einfach:

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

Als so einfach, wie es diese Lösung hat seine Grenzen sein kann - es ist nicht weder Binding noch DynamicResource Erweiterungen für oben genannte Eigenschaften nicht unterstützt. Dies ist jedoch erreichbar, erfordert aber etwas mehr Mühe. Binding Unterstützung sollte ziemlich einfach sein - eine Frage der richtigen Verwendung von XamlSetMarkupExtensionAttribute  (Plus einiger Standardcode). DynamicResource Unterstützung wäre ein wenig komplizierter, und zusätzlich zu XamlSetMarkupExtensionAttribute Verwendung erfordern würde, die IServiceProvider zurückzukehren ausreichend IProvideValueTarget Implementierung, ist aber immer noch möglich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top