I have a rectangle which I want to make visible, then I want to wait for 500 milliseconds, then I want to make it invisible again.
Initially I tried this code:
MuzzleFlash.Visibility = Visibility.Visible;
Thread.Sleep(500);
this.UpdateLayout();
this.InvalidateVisual();
MuzzleFlash.Visibility = Visibility.Collapsed;
I tried those two intermediate lines as they supposedly forced windows to update, but all this did was pause for half a second without changing any sort of rectangles.
So I heard about BackgroundWorkers and how they're what I should use. After some brief reading, I came up with this. Note that Shoot is subscribed to a MouseDown event on a Canvas, which worked previously:
private void Shoot(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
BackgroundWorker UIUpdater = new BackgroundWorker();
UIUpdater.WorkerSupportsCancellation = true;
UIUpdater.WorkerReportsProgress = false;
UIUpdater.DoWork += new DoWorkEventHandler(UI_DoWork);
UIUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(cancelUIUpdate);
}
private void UI_DoWork(object sender, DoWorkEventArgs e)
{
MuzzleFlash.Visibility = Visibility.Visible;
Thread.Sleep(500);
this.UpdateLayout();
this.InvalidateVisual();
MuzzleFlash.Visibility = Visibility.Collapsed;
}
private void cancelUIUpdate(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
bw.CancelAsync();
}
Now it doesn't even pause for half a second, indicating to me that the worker isn't doing anything. How can I fix this, and make the rectangle appear/disappear?
It is bad idea to use background worker to manage animation in wpf. Animation should run from Storyboard. It can be specified through xaml or in code.
Your question of animating a rectangle is very simple with xaml:
<Rectangle x:Name="MuzzleFlash" Height="100" Width="100" Fill="Red">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0.5" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
For more complex animations, you can use Blend to design them interactively.
Updated response after comments: If you want to make appear and disappear, you have to manipulate it from a parent container, as once rectangle hidden, it won't respond to mouse events.
You can put the rectangle in a grid and reference it by name to change its visibility in animation.
<Grid Background="Gray">
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseDown">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="0:0:0.0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="MuzzleFlash">
<DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" />
<DiscreteObjectKeyFrame KeyTime="0:0:0.5" Value="{x:Static Visibility.Hidden}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Rectangle x:Name="MuzzleFlash" Height="100" Width="100" Fill="Red">
</Rectangle>
</Grid>