0

I have trying a simple repeat animation on xaml page as below:

<StackPanel Canvas.Left="1" Canvas.Top="1">
    <StackPanel.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard x:Name="sb_PathGeometry" RepeatBehavior="Forever">
                     <PointAnimationUsingPath Storyboard.TargetName="PathGeometry"  
                          Storyboard.TargetProperty="Center"  
                          Duration="0:0:1">
                          <PointAnimationUsingPath.PathGeometry>
                              <PathGeometry Figures="M 10,0 L 10,-182 L -199,-182" />
                          </PointAnimationUsingPath.PathGeometry>
                     </PointAnimationUsingPath>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </StackPanel.Triggers>
</StackPanel>

Then after that, I plan to get control on idle page with the code below (Find from another site):

using System.Windows.Threading;
using System.Windows.Interop;

namespace DS
{
    public partial class MontagePage : Page
    {
        private EventHandler handler;

        public MontagePage()
        {
            InitializeComponent();

            handler = delegate
            {
                DispatcherTimer timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(4);
                timer.Tick += delegate
                {
                    if (timer != null)
                    {
                        timer.Stop();
                        timer = null;
                        System.Windows.Interop.ComponentDispatcher.ThreadIdle -= handler;
                        ComponentDispatcher_ThreadIdle();
                        System.Windows.Interop.ComponentDispatcher.ThreadIdle += handler;
                    }
                };
                timer.Start();

                //System.Windows.Interop.ComponentDispatcher.ThreadIdle -= handler;
                Dispatcher.CurrentDispatcher.Hooks.OperationPosted += delegate
                {
                    if (timer != null)
                    {
                        timer.Stop();
                        timer = null;
                    }
                };
            };

            ComponentDispatcher.ThreadIdle += handler;
        }

        void ComponentDispatcher_ThreadIdle()
        {
            //Go to IdlePage.xaml
            IdlePage idlepage = new IdlePage();
            this.NavigationService.Navigate(idlepage);
        }
    }
}

The problem that I can summarize is:

  1. Because of that animation running on forever, the idle control is not firing. How to make it work?
jimi
  • 5
  • 6

2 Answers2

0

* PART 1 *

you are creating new timers every time you enter your delegate block.

Note from MSDN:

Setting Enabled to true is the same as calling Start, while setting Enabled to false is the same as calling Stop.

So first step I would recommend at least to refactor your code to just reset enabled

//sorry I changed your delegates to lambda's for my convenience (personal pref), but the point stands
public MontagePage()
    {
        InitializeComponent();
        timer.Interval = TimeSpan.FromSeconds(4);

        handler = (s1,a1) =>
        {
            timer.Tick += (s2, a2) =>
            {
                if (timer.IsEnabled)
                {
                    timer.IsEnabled = false;
                    ComponentDispatcher.ThreadIdle -= handler;
                    ComponentDispatcher_ThreadIdle();
                    ComponentDispatcher.ThreadIdle += handler;
                }
            };
            timer.Start();

            Dispatcher.CurrentDispatcher.Hooks.OperationPosted 
                += (s, a)
                    =>
                    {
                        if (timer.IsEnabled)
                            timer.IsEnabled = false;
                    };
        };

        ComponentDispatcher.ThreadIdle += handler;
    }

* Part 2:*

Remove the RepeatBehavior="Forever" and you code will start firing according to the timer.

denis morozov
  • 6,236
  • 3
  • 30
  • 45
  • Hi denis morozov, Tq fr da answer but..in my condition, i cannot remove the RepeatBehavior="Forever". Bcoz i want that animation playing in that way. I just want to know how to get the idle control based on mousemovement? not by using the timer when that animation is stop(). – jimi Apr 26 '12 at 02:29
0

Putting this in a different answer, because the approach is different. Change your timer to system timer to leverage on timer.elapsed, where you can spawn an action on a different thread.

 public MontagePage()
    {
        InitializeComponent();

        var timer = new System.Timers.Timer {Interval = 4000, Enabled = true};
        timer.Elapsed += (s, a) => Task.Factory.StartNew(ComponentDispatcher_ThreadIdle);

        .....

this will work without you changing your XAML.

denis morozov
  • 6,236
  • 3
  • 30
  • 45
  • I get this error "The calling thread must be STA, because many UI components require this.". And can u elaborate more on details? Tq. – jimi Apr 26 '12 at 02:31