The thing to remember though is in order to have a nice looking animation, it should not lock the UI while running. If it does, you probably won't have a chance to see the animation happen!
So, here is a small sample of how to do this:
We start with our WPF window:
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<Label Margin="5">Press button to start work:</Label >
<Button Name="btnStart" Width="100" Height="25" Content="Start!"
Margin="5" Click="btnStart_Click" />
<Image Name="imgWork" Source="/WPFTestApp;component/Image/working.png"
Width="40" Margin="5"></Image>
<Label Name="lblDone" Visibility="Hidden" HorizontalAlignment="Center">Done!</Label>
</StackPanel >
</Grid>
I simply added a button that starts the animation and a label that will appear once done. An image that spins will be my animating object.
Now on to the code:
We need to reference the following:
System.Windows.Media.Animation; // For the animation System.Windows.Threading; // For the threading System.ComponentModel; // For the background worker processesThere are a few ways to go around this problem, but I find that using background worker processes is the most easy and clean way to code the solution.
So, we need to initialize a background worker and instruct it what to do:
_bg = new BackgroundWorker(); _bg.DoWork += delegate(object s, DoWorkEventArgs e) { lblDone.Visibility = System.Windows.Visibility.Hidden; animateButton(imgWork); System.Threading.Thread.Sleep(5000); }; _bg.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs e) { disableAnimation(imgWork); lblDone.Visibility = System.Windows.Visibility.Visible; };Let's declare the animateButton and disableAnimation methods:
private void animateButton(Image target) { if (target.Dispatcher.CheckAccess()) { DoubleAnimation da = new DoubleAnimation (360, 0, new Duration(TimeSpan.FromSeconds(3))); RotateTransform rt = new RotateTransform(); target.RenderTransform = rt; target.RenderTransformOrigin = new Point(0.5, 0.5); da.RepeatBehavior = RepeatBehavior.Forever; rt.BeginAnimation(RotateTransform.AngleProperty, da); } else { target.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => { DoubleAnimation da = new DoubleAnimation (360, 0, new Duration(TimeSpan.FromSeconds(3))); RotateTransform rt = new RotateTransform(); target.RenderTransform = rt; target.RenderTransformOrigin = new Point(0.5, 0.5); da.RepeatBehavior = RepeatBehavior.Forever; rt.BeginAnimation(RotateTransform.AngleProperty, da); })); } } private void disableAnimation(Image target) { if (target.Dispatcher.CheckAccess()) { target.RenderTransform = null; } else { target.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => { target.RenderTransform = null; })); } }I use Dispatcher.CheckAccess to ensure that the calling thread has access to the object. If not, I invoke what I need to do in a separate thread.
So, all we need now is to add the code for the button:
_bg.RunWorkerAsync();to run the background worker asynchronously.
That's it!
No comments:
Post a Comment