Monday, December 31, 2012

Making smooth effect in WPF manually in C# with DispatcherTimer

Making smooth effect in WPF manually in C# with DispatcherTimer

I'm trying to make pretty effect with not using Storyboard or another ready/already done stuff in WPF.

I want to make smooth effect, where on some event (like click) the UI element resizes for 2-3 seconds and bluring with changing color. All these items I want to make in smooth pretty way.

I have prepared such class to render each frame of my effect:

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

Here I'm trying to make it work with 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();             }    } 

The main problem is, that when I'm launcing it, I'm only waiting and at the final time ( when must last frame be rendered ) , I'm getting in a very quick speed all frames, but perviously there was nothing.

How to solve it and make perfect smooth effect in pure C# way with not using some ready/done stuff?

Thank you!

Answers & Comments...

Answer: 1

The ApplicationHelper.DoEvents() in dt_Tick probably does nothing, since there are no events to process. At least not the ones you're probably expecting.

If I'm not mistaken, your code will just quickly set the Radius to 0, then 1, 2, and so on in quick succession, and finally to 19. All of that will happen every 500 milliseconds (on every Tick, that is).

I think you might believe that each Tick will only set Radius to one value and then wait for the next Tick, but it does not. Every Tick will set the Radius to all the values, ending at 19. That is one possible explanation for what you're experiencing.

I would also like to comment on the DoEvents approach. It's most likely a bad idea. Whenever I see a DoEvents I get chills up my spine. (It reminds me of some seriously bad Visual Basic 5/6 code I stumbled across 10-15 years ago.) As I see it, an event handler should return control of the GUI thread as quickly as possible. If the operation takes a not insignificant amount of time, then you should delegate that work to a worker thread. And nowadays, you have plenty of options for writing asynchronous code.

by : Christoffer Lettehttp://stackoverflow.com/users/11808




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog