none
Animation ausführen wenn ... RRS feed

  • Frage

  • Hallo!

    Ich habe ein Storyboard mit mehreren Animationen.

    <BeginStoryboard>
        <Storyboard >
            <DoubleAnimation 1 ... />
            <DoubleAnimation 2 ... />
            <DoubleAnimation 3 ... />
        </Storyboard>
    </BeginStoryboard>
    

    Nun möchte ich in Abhängigkeit einer Eigenschaft die zweite Animation ausführen oder auch nicht.

    Wie kann ich das denn steuern???

    Fred.

    Dienstag, 11. Dezember 2018 15:30

Antworten

  • Hi Fred,
    für solche Bedingungen im XAML sehe ich keinen Lösungsweg. Zu lösen ist das aber problemlos per Code, indem in Abhängigkeit von einer Eigenschaft die entsprechenden Animationen hinzugefügt werden.

    Und hier noch eine Demo:

    XAML:

    <Window x:Class="WpfApp1.Window82"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window82" Height="450" Width="800">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <CheckBox Name="cb" Content="Unchecked - Drehung links, Checked - Drehung rechts"/>
        <Button Grid.Row="1" Content="Animation starten" Click="Button_Click"/>
        <Grid Grid.Row="2">
          <Rectangle Name="rec" Fill="Red" Stroke="Black" Height="100" Width="100">
            <Rectangle.LayoutTransform>
              <RotateTransform/>
            </Rectangle.LayoutTransform>
          </Rectangle>
        </Grid>
      </Grid>
    
    </Window>
    

    Und dazu der Codebehind:

    using System;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    
    namespace WpfApp1
    {
      /// <summary>
      /// Interaction logic for Window82.xaml
      /// </summary>
      public partial class Window82 : Window
      {
        public Window82()
        {
          InitializeComponent();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          DoubleAnimation an = new DoubleAnimation
          {
            AutoReverse = true,
            Duration = new Duration(TimeSpan.FromSeconds(1))
          };
          Storyboard.SetTargetName(an, "rec");
          DependencyProperty[] depProps = new DependencyProperty[] 
          { Rectangle.LayoutTransformProperty, RotateTransform.AngleProperty };
          PropertyPath propPath = new PropertyPath("(0).(1)", depProps);
          Storyboard.SetTargetProperty(an, propPath);
          if (cb.IsChecked.Value)
          {
            an.From = 0;
            an.To = 100;
          }
          else
          {
            an.From = 0;
            an.To = -100;
          }
          Storyboard sb = new Storyboard();
          sb.Children.Add(an);
          sb.Begin(this);
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    • Bearbeitet Peter Fleischer Dienstag, 11. Dezember 2018 20:31
    • Als Antwort markiert perlfred Mittwoch, 12. Dezember 2018 07:16
    Dienstag, 11. Dezember 2018 19:15

Alle Antworten

  • Hi Fred,
    für solche Bedingungen im XAML sehe ich keinen Lösungsweg. Zu lösen ist das aber problemlos per Code, indem in Abhängigkeit von einer Eigenschaft die entsprechenden Animationen hinzugefügt werden.

    Und hier noch eine Demo:

    XAML:

    <Window x:Class="WpfApp1.Window82"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window82" Height="450" Width="800">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="Auto"/>
          <RowDefinition Height="Auto"/>
          <RowDefinition/>
        </Grid.RowDefinitions>
        <CheckBox Name="cb" Content="Unchecked - Drehung links, Checked - Drehung rechts"/>
        <Button Grid.Row="1" Content="Animation starten" Click="Button_Click"/>
        <Grid Grid.Row="2">
          <Rectangle Name="rec" Fill="Red" Stroke="Black" Height="100" Width="100">
            <Rectangle.LayoutTransform>
              <RotateTransform/>
            </Rectangle.LayoutTransform>
          </Rectangle>
        </Grid>
      </Grid>
    
    </Window>
    

    Und dazu der Codebehind:

    using System;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    
    namespace WpfApp1
    {
      /// <summary>
      /// Interaction logic for Window82.xaml
      /// </summary>
      public partial class Window82 : Window
      {
        public Window82()
        {
          InitializeComponent();
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          DoubleAnimation an = new DoubleAnimation
          {
            AutoReverse = true,
            Duration = new Duration(TimeSpan.FromSeconds(1))
          };
          Storyboard.SetTargetName(an, "rec");
          DependencyProperty[] depProps = new DependencyProperty[] 
          { Rectangle.LayoutTransformProperty, RotateTransform.AngleProperty };
          PropertyPath propPath = new PropertyPath("(0).(1)", depProps);
          Storyboard.SetTargetProperty(an, propPath);
          if (cb.IsChecked.Value)
          {
            an.From = 0;
            an.To = 100;
          }
          else
          {
            an.From = 0;
            an.To = -100;
          }
          Storyboard sb = new Storyboard();
          sb.Children.Add(an);
          sb.Begin(this);
        }
      }
    }


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks


    • Bearbeitet Peter Fleischer Dienstag, 11. Dezember 2018 20:31
    • Als Antwort markiert perlfred Mittwoch, 12. Dezember 2018 07:16
    Dienstag, 11. Dezember 2018 19:15
  • Hallo Peter!

    Danke! für die "Ernüchterung" :-)

    Der Versuch war es wert, da es schon in XAML eine recht umfangreiche Steuerung geworden ist.

    Also dann mal ran an den Speck ... oder Storyboard.

    Mittwoch, 12. Dezember 2018 08:24
  • Hi Fred,
    ich würde einfach die Funktionalitäten (z.B. StoryBoard) so kapseln, dass ich es dann einfach irgendwo im XAML nachnutzen kann.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP für Developer Technologies)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 12. Dezember 2018 08:39
  • Hallo Peter!

    Praktisch funktioniert es, aber ich weis nicht, ob das immer so ist ...

    Die Animationen werden durch einen Expander -> das Event Expanded und Collapsed gesteuert:

    <Expander Expanded="Expander_Expanded">
        <Expander.Triggers>
            <EventTrigger RoutedEvent="Expander.Expanded">
                <BeginStoryboard>
                    <Storyboard >
                        <DoubleAnimation 1 ...  />
                        <DoubleAnimation 2 ...  />
                        <DoubleAnimation 3 
      x:Name="daExpander_Expanded_Auftraege" From="0" To="300" ... />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Expander.Triggers>
    </Expander>

    Ich habe der Animation 3 einen Namen gegeben (daExpander_Expanded_Auftraege) und das Event Expanded so zu sagen doppelt belegt. Einmal im XAML-Trigger und einmal beim Expander-Event (Expander_Expanded)

    Im Eventhandler (CodeBehind) greife ich auf die (benannte) DoubleAnimation zu und setze, abhängig von der Eigenschaft, den gewünschten Wert:

    private void Expander_Expanded(object sender, RoutedEventArgs e)
    {
        daExpander_Expanded_Auftraege.To = lAuftraege == true ? 300 : 0;    // Wenn Aufträge vorhanden sind, diese anzeigen
    }

    Die Arbeitsweise basiert also darauf, dass der Event-Handler immer zuerst ausgeführt wird (und die Werte überschreibt) und der Trigger nur noch die Animation(en) (mit den gesetzten Wert(en)) ausführt.

    Ist das gewährleistet?


    • Bearbeitet perlfred Mittwoch, 12. Dezember 2018 09:37
    Mittwoch, 12. Dezember 2018 09:34