页面上的WPF空闲控制与故事板“RepeatBehavior =”Forever“”

时间:2012-04-25 10:27:51

标签: wpf controls storyboard python-idle

我在xaml页面上尝试了一个简单的重复动画,如下所示:

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

然后,我计划使用下面的代码控制空闲页面(从其他网站查找):

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

我可以总结的问题是:

  1. 由于该动画永远运行,因此空闲控制不会触发。如何使它工作?

2 个答案:

答案 0 :(得分:0)

*第1部分*

每次输入代理区块时都会创建新的计时器。

来自MSDN的说明:

将Enabled设置为true与调用Start相同,而将Enabled设置为false与调用Stop相同。

所以第一步我建议至少重构你的代码只重置启用

//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;
    }

*第2部分:*

删除RepeatBehavior =“Forever” 并且您的代码将根据计时器开始触发。

答案 1 :(得分:0)

将其置于不同的答案中,因为方法不同。将您的计时器更改为系统计时器以利用timer.elapsed,您可以在其他线程上生成操作。

 public MontagePage()
    {
        InitializeComponent();

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

        .....

无需更改XAML即可使用。