Остановить анимацию WPF, запуск раскадровки в xaml, но остановить ее в codebehind?

#c# #wpf #xaml

#c# #wpf #xaml

Вопрос:

Я создал анимационную раскадровку в файле xaml. Эта раскадровка начинается при нажатии кнопки. Но чтобы остановить анимацию, я пытаюсь остановить раскадровку в моем пользовательском событии в code behind. Код не выдает никаких исключений, но когда мое событие было запущено, анимация все еще продолжается.

Я думаю, проблема в методе Stop. Для остановки требуется тот же объект, с которого начинается анимация. Но здесь раскадровка начинается в WPF xaml, и я останавливаю ее в коде позади.

Любое решение, как получить объект Xaml в коде позади или любое альтернативное решение для этого??

КОД XAML:

 <Canvas.Triggers>
            <EventTrigger RoutedEvent="Button.Click" SourceName="ScanButton">
                <EventTrigger.Actions>
                    <BeginStoryboard >
                        <Storyboard  Name="MovingServer" Storyboard.TargetName="ImageMove" RepeatBehavior="Forever" >
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="30" To="300" BeginTime="0:0:0" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="300" To="300" BeginTime="0:0:5" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="300" To="600" BeginTime="0:0:7" />
                            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1" To="0" BeginTime="0:0:7" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger.Actions>
            </EventTrigger>
  

Код позади:

     private void EventPublisher_OnScanningFinish(object sender, EventArgs args)
    {
        Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() { this.StopScanningAnimation(); });
    }

    private void StopScanningAnimation()
    {

        ServerView.StoryBoardServerScrolling.Stop(this); //---------- Not Working

        //this.ServerView.Server1Static.Visibility = System.Windows.Visibility.Hidden;
        //this.ServerView.Server2Static.Visibility = System.Windows.Visibility.Hidden;
        //this.ServerView.Server3Scrolling.Visibility = System.Windows.Visibility.Hidden;
        //this.ServerView.SearchingGlass.Visibility = System.Windows.Visibility.Hidden;
    }
  

Ответ №1:

Определите раскадровку как статический ресурс,

 <MyControl.Resources>
                        <Storyboard Key="MovingServer" Storyboard.TargetName="ImageMove" RepeatBehavior="Forever" >
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="30" To="300" BeginTime="0:0:0" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="300" To="300" BeginTime="0:0:5" />
                            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="300" To="600" BeginTime="0:0:7" />
                            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1" To="0" BeginTime="0:0:7" />
                        </Storyboard>
</MyControl.Resources>
  

и ссылаться на это из вашего внутреннего кода следующим образом :

 StoryBoard board = (StoryBoard)this.FindResource("MovingServer");
board.stop();
  

запустите анимацию из события «click» кнопки (я не знаю, определено ли это вами в xaml, но вот как это было бы сделано, если бы вы это сделали)

 <Button x:Name="ScanButton" onClick="Scanbutton_Click"></button>


protected void Scanbutton_Click(object Sender, EventArgs e)
{
    StoryBoard board = (StoryBoard)this.FindResource("MovingServer");
    board.start();
}
  

Комментарии:

1. Вы это тестировали? StaticResources ? Вы имели в виду просто Resources ? Что насчет x:Key ?

2. Я тестирую пример кода, который работает, но мой текущий реальный код слишком длинный, поэтому я ищу альтернативы

3. @H.B. Извините, не могу протестировать этот код прямо сейчас. вы правы со StaticResources, это должно быть ‘resources’, я изменю это прямо сейчас. Ключ x:; часть ‘x:’ необязательна

4. Просто хотел указать на тот факт, что вам нужно добавить ключ вместо имени. Также: у меня была та же идея, и я попробовал ее, похоже, анимация тоже не останавливается.

5. @ Я пробовал с ресурсом Windows… Это не работает… K Обновить его

Ответ №2:

Я благодарен Тимоти за то, что он подал хорошую идею. Здесь я публикую свой рабочий код

    /*create this resources as global to that perticular xaml. Need not to be put it in App.xaml
     MyControl could be Window or Page or UserControl */

       <MyControl.Resources>
        <Storyboard x:Key="MovingServer" Storyboard.TargetName="MyImage" RepeatBehavior="Forever" >
            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="30" To="300" BeginTime="0:0:0" />
            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" From="300" To="300" BeginTime="0:0:5" />
            <DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:2" From="300" To="600" BeginTime="0:0:7" />
            <DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:2" From="1" To="0" BeginTime="0:0:7" />
        </Storyboard>
    </MyControl.Resources>

/* <!-- Now use those animation resources, the place where you want. You can use it as static resource and begin stop animation from code behind OR use it as trigger event --> */

/*    <!-- Static resources--> */
    <Canvas>
        <Image Canvas.Left="0" Canvas.Top="-2" Height="32" Name="MyImage" Width="32" Source="/CCTrayHelper;component/Images/ServerIcon.png" Visibility="Hidden"/>
     <Canvas.Resources>
        <BeginStoryboard x:Key="serverAnimate" Storyboard="{StaticResource MovingServer}" />
     </Canvas.Resources>
    </Canvas>
    <Button x:Name="ScanButton" onClick="Scanbutton_Click" />

/* ****************************************************************** */



  /*  Code behind to start/stop animation*/

//Get the resource value first on current object, so that when you start/stop the animation, it work only on current object
  Storyboard sbImageAnimate = (Storyboard)this.ServerView.FindResource("MovingServer");

//Start the animation on Button Click 
 protected void Scanbutton_Click(object Sender, EventArgs e)
  {   
   this.MyImage.Visibility = System.Windows.Visibility.Visible; 
   sbImageAnimate.Begin();
  } 

 //Stop animation on my own even. You can use it on any event
 private void EventPublisher_OnFinish(object sender, EventArgs args) 
 {   
      Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() { this.StopScanningAnimation(); });  
 }

 private void StopScanningAnimation()  
   {
   sbImageAnimate.Stop();
   this.MyImage.Visibility = System.Windows.Visibility.Hidden; 
   } 
  

Ответ №3:

Я решаю проблему с помощью Stop() метода класса Storyboard следующим образом

 myStoryBoard.Stop(this.LayoutRoot);
  

с помощью этого решения вам не нужно объявлять раскадровку на ресурсе.

Комментарии:

1. Чтобы это было возможно, при запуске анимации вы должны установить второму параметру значение true: Begin(DependencyObject…, разрешает модификацию).