使用DispatcherTimer在C#中手动生成WPF中的平滑效果

时间:2012-12-26 14:46:14

标签: wpf silverlight effects dispatcher smooth

我试图在WPF中不使用Storyboard或其他已准备/已经完成的东西时效果很好。

我想制作平滑效果,在某些事件(如点击)上,UI元素调整大小2-3秒,并随着颜色的变化而模糊。我想以平滑的方式制作所有这些物品。

我准备了这样的类来渲染我效果的每一帧:

public static class ApplicationHelper
{
        [SecurityPermissionAttribute(SecurityAction.Demand,
        Flags=SecurityPermissionFlag.UnmanagedCode)]
        public static void DoEvents(DispatcherPriority priority)
        {
            DispatcherFrame frame = new DispatcherFrame();
            DispatcherOperation oper = Dispatcher.CurrentDispatcher.
                            BeginInvoke(priority,
                            new DispatcherOperationCallback(ExitFrameOperation),
                            frame);

            Dispatcher.PushFrame(frame);
            if (oper.Status != DispatcherOperationStatus.Completed)
            {
                oper.Abort();
            }
        }

        private static object ExitFrameOperation(object obj)
        {
            ((DispatcherFrame)obj).Continue = false;
            return null;
        }

        [SecurityPermissionAttribute(SecurityAction.Demand,
        Flags=SecurityPermissionFlag.UnmanagedCode)]
        public static void DoEvents()
        {
            DoEvents(DispatcherPriority.Background);
        }
}

我在这里尝试使用DispatcherTimer:

   void vb1_click(object sender, System.Windows.Input.MouseButtonEventArgs e)
   {
       DispatcherTimer dt = new DispatcherTimer();
       dt.Interval = new TimeSpan(0, 0, 0, 0, 500);
       dt.Tick += new System.EventHandler(dt_Tick);
       dt.Start();
   }

   void dt_Tick(object sender, System.EventArgs e)
   {
       for(int i = 0; i < 20; i++)
       {
           this.vb2_blur_eff.Radius = (double)i;
           ApplicationHelper.DoEvents();     
       }
   }

主要的问题是,当我正在进行它时,我只是在等待并且在最后一次(必须在最后一帧被渲染时),我所有帧都以非常快的速度进入,但是在那里没什么。

如何解决它并以纯C#方式制作完美平滑效果而不使用一些准备好/做过的东西?

谢谢!

1 个答案:

答案 0 :(得分:2)

ApplicationHelper.DoEvents()中的dt_Tick可能无效,因为没有要处理的事件。至少不是你可能期待的那些。

如果我没有弄错的话,您的代码会快速将Radius设置为0,然后12等,并快速连续设置,最后到19。所有这些都将每500毫秒发生一次(每Tick个就是这样)。

我认为您可能认为每个Tick只会将Radius设置为一个值,然后等待下一个Tick,但事实并非如此。每个Tick都会将Radius设置为所有值,以19结尾。这是您正在经历的一种可能的解释。

我还想对DoEvents方法发表评论。这很可能是一个坏主意。每当我看到DoEvents时,我的脊椎就会变冷。 (它让我想起了一些严重不好的Visual Basic 5/6代码,我偶然发现了10到15年前。)正如我所看到的,事件处理程序应该尽快返回GUI线程的控制权。如果操作花费的时间不是很少,那么您应该将该工作委托给工作线程。现在,您有很多编写异步代码的选项。