Constraining dimension of a PlaneProjection - silverlight

How can I constrain a plane projection to a particular dimension? For example, I have the following:
<Canvas Width="720" Height="540" x:Name="Root" Background="Red" >
<Line Width="200" Height="5" X1="0" X2="200"
Y1="0" Y2="0" Stroke="LimeGreen" StrokeThickness="10"
Canvas.Left="260" Canvas.Top="70" />
<Rectangle Width="200" Height="400" Stroke="Blue" StrokeThickness="6"
Fill="LightBlue" Opacity="0.5" Canvas.Left="260" Canvas.Top="70">
<Rectangle.Projection>
<PlaneProjection x:Name="box" />
</Rectangle.Projection>
</Rectangle>
<Line Width="200" Height="10" X1="0" X2="200"
Y1="0" Y2="0" Stroke="LimeGreen" StrokeThickness="10"
Canvas.Left="260" Canvas.Top="464" />
</Canvas>
I want to rotate this around its Y axis by 360 degrees, but never want the projection to exceed the bounds of the height of the rectangle - in this case, 400 points.
The storyboard, just for simplicities' sake in testing, is in a trigger.
<UserControl.Triggers>
<EventTrigger>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="box"
Storyboard.TargetProperty="RotationY"
By="360" Duration="0:0:15"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>

This is not perfect, as it is linear interpolation and the actual relationship of the height to angle of rotation is a slight sinusoidal curve, but is close to what you want.
It basically scales Y to 0.88 in one quarter of the total time (and is AutoReversed).
You can simplify the element naming as you did with "box" if you prefer (I used Blend to author/test the storyboard and it always creates the long element names):
<Storyboard>
<DoubleAnimation Storyboard.TargetName="box"
Storyboard.TargetProperty="RotationY"
By="360" Duration="0:0:15"
RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)"
Storyboard.TargetName="rectangle"
Duration="0:0:3.75" To="0.88"
RepeatBehavior="Forever"
AutoReverse="True" >
</DoubleAnimation>
</Storyboard>
<Rectangle x:Name="rectangle"
Stroke="Blue"
StrokeThickness="6"
Fill="LightBlue"
Opacity="0.5"
RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<CompositeTransform/>
</Rectangle.RenderTransform>
<Rectangle.Projection>
<PlaneProjection x:Name="box" />
</Rectangle.Projection>
</Rectangle>

Related

WPF anchor Grid OpacityMask for Moving Grid Content

I have a hexagonal Polygon that I am trying to use as an OpacityMask, then have content inside the polygon that can scroll and be clipped at the edges. The problem I encounter is that as the content moves, the OpacityMask moves with it (though by a different amount). Below is my code:
<Window Title="MainWindow" Height="450" Width="800">
<Grid Height="450" Width="800">
<StackPanel>
<Grid ClipToBounds="True">
<Grid.OpacityMask >
<VisualBrush Stretch="None" >
<VisualBrush.Visual>
<Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Fill="Black" />
</VisualBrush.Visual>
</VisualBrush>
</Grid.OpacityMask>
<Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Stroke="Black" StrokeThickness="5"/>
<Rectangle x:Name="TestRectangle" Height="400" Width="400" Fill="Red" />
</Grid>
<Button Content="Testing" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetName="TestRectangle" Storyboard.TargetProperty="Margin"
BeginTime="0:0:0" Duration="0:0:0.5" To="-400,0,0,0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Grid>
</Window>
How do I anchor the opacity mask so that the grid content can move with the mask remaining stationary?
Edit: Answer Results and Additional Testing
Using the code in an answer provided, I still get movement of the hexagon:
Begin:
Begin State
End:
End State
However, I have found that by adding a second rectangle that is transparent and that moves in the opposite direction of the red rectangle, I achieve the desired result. While this does work, it seems like there should be a better way to do it.
If you try to set the margin of the rectangle directly, you would notice that it is ignored inside a grid. So one way to solve that would be to put the rectangle inside a border and animate the margin for that border
<Window x:Class="StackverflowTests.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackverflowTests"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Height="450" Width="810">
<StackPanel>
<Grid ClipToBounds="True">
<Grid.OpacityMask >
<VisualBrush Stretch="None" >
<VisualBrush.Visual>
<Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Fill="Black" />
</VisualBrush.Visual>
</VisualBrush>
</Grid.OpacityMask>
<Polygon Points="220,225 310,69 490,69 580,225 490, 381 310, 381" Stroke="Black" StrokeThickness="5"/>
<Border x:Name="TestRectangle">
<Rectangle Height="400" Width="400" Fill="#ff0000"/>
</Border>
</Grid>
<Button Content="Testing" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Storyboard.TargetName="TestRectangle" Storyboard.TargetProperty="Margin"
BeginTime="0:0:0" Duration="0:0:0.5" To="-400,0,0,0" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Grid>

Fun roulette ellipse image rotation (not 360)

I am creating fun roulette game where I am trying to rotate eclipse with wheel image inside on its axis (but not 360 degree). Right now, some problem with its rotation, its not rotating as per my requirement. If you will run below code with images attached also. you will get my requirement.
Pls set your screen resolution i.e. Height="1024" Width="768" for understanding my exact requirement. I am also attaching images here. one is background image and another is wheel image.
I am stuck on this from last one week. Any help will be appreciable. Thanks in advance.
Title="MainWindow" Height="1024" Width="768"
WindowStyle="None"
WindowStartupLocation="CenterScreen" WindowState="Maximized">
<Window.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames RepeatBehavior="Forever" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="ball">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="360" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Image/fun_roulette.jpg" />
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Ellipse Name="ball" Stroke="Black"
RenderTransformOrigin="0.5,0.5" Width="370" Height="200"
Grid.Row="0" Grid.Column="0" Opacity=".4"
Margin="0,30,0,0"
>
<Ellipse.RenderTransform>
<TransformGroup >
<ScaleTransform />
<SkewTransform />
<RotateTransform Angle="45" CenterX="0" CenterY="0" />
<TranslateTransform />
</TransformGroup>
</Ellipse.RenderTransform>
<Ellipse.Fill>
<ImageBrush ImageSource="Image/Roullette_Wheel.jpg" />
</Ellipse.Fill>
<Ellipse.BitmapEffect>
<BevelBitmapEffect BevelWidth="0" />
</Ellipse.BitmapEffect>
<Ellipse.BitmapEffectInput>
<BitmapEffectInput />
</Ellipse.BitmapEffectInput>
</Ellipse>
</Grid>
Download Background Image from here
https://drive.google.com/file/d/0ByTbA6S0c1TaZEo2akgtQjVCbjQ/view?usp=sharing
Download Wheel Image from here
https://drive.google.com/file/d/0ByTbA6S0c1TaY1JzazhudDkzMjA/view?usp=sharing
As I understand you want the ellipse to rotate exactly at the position of the static disc in the background image. Also because of a little 3D effect (perspective effect), rotating the ellipse normally would not be able to produce the desired result. You can try using some 3D feature in WPF but it's some kind of overkill because we still have another choice.
Instead of rotating the whole ellipse, you can just rotate the ImageBrush. I've tried your code and tweaking it a little with some modifications and finally the effect seems to be what you want. Here is the code:
<Window.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames RepeatBehavior="Forever"
Storyboard.TargetProperty="Angle" Storyboard.TargetName="rot">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:2" Value="360" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="Image/fun_roulette.jpg" />
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Ellipse Name="ball" Stroke="Black" RenderTransformOrigin="0.5,0.8"
Grid.Row="0" Grid.Column="0" Opacity=".4"
Margin="6,0,0,0">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX=".195" ScaleY=".45"/>
</Ellipse.RenderTransform>
<Ellipse.Fill>
<ImageBrush ImageSource="Image/Roullette_Wheel.jpg">
<ImageBrush.RelativeTransform>
<TransformGroup >
<RotateTransform CenterX="0.5" CenterY="0.5" x:Name="rot"/>
<SkewTransform/>
<TranslateTransform />
</TransformGroup>
</ImageBrush.RelativeTransform>
</ImageBrush>
</Ellipse.Fill>
<Ellipse.BitmapEffect>
<BevelBitmapEffect BevelWidth="0" />
</Ellipse.BitmapEffect>
<Ellipse.BitmapEffectInput>
<BitmapEffectInput />
</Ellipse.BitmapEffectInput>
</Ellipse>
</Grid>
You should copy and try this exact code, try scanning it for some differences from your original code.

Animation slows down when left margin becomes negative

I am trying to have a polygon move from completely off the left of the screen, across the screen, and then completely off the right of the screen, then back again.
I've gotten this working. BUT, for some reason, as soon as the left margin becomes negative, the animation suddenly slows down. As soon as the left margin becomes positive, it speeds up again.
Why does this happen? How can I stop it?
Here's the complete code that demonstrates this:
<Window x:Class="Geometry.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<PathGeometry x:Key="MyGeometry">
<PathGeometry.Figures>
<PathFigure>
<PathFigure.Segments>
<LineSegment Point="0.30,0" />
<LineSegment Point="0.70,1" />
<LineSegment Point="0.40,1" />
<LineSegment Point="0,0" />
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
<Storyboard x:Key="MovingAnimation">
<ThicknessAnimationUsingKeyFrames RepeatBehavior="1:0:0" FillBehavior="HoldEnd" Storyboard.TargetName="_path" Storyboard.TargetProperty="Margin" >
<DiscreteThicknessKeyFrame KeyTime="0:0:0" Value="-2.0,0,0,0" />
<LinearThicknessKeyFrame KeyTime="0:0:10" Value="1.0,0,0,0" />
<LinearThicknessKeyFrame KeyTime="0:0:20" Value="-2.0,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard Storyboard="{StaticResource MovingAnimation}" ></BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label>Margin:</Label>
<TextBlock Text="{Binding ElementName=_path, Path=Margin.Left, StringFormat={}{0:0.#}}" />
</StackPanel>
<Canvas Name="_canvas" Grid.Row="1">
<Border Margin="0" Width="1" Height="1" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border.RenderTransform>
<ScaleTransform
ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}"
ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
CenterX="0"
CenterY="0">
</ScaleTransform>
</Border.RenderTransform>
<Path
Name="_path"
Fill="#CCCCFF"
Data="{StaticResource MyGeometry}"
Width="1.0"
Height="1.0"
>
</Path>
</Border>
</Canvas>
</Grid>
</Window>
I don't have an explanation why the negative margin animates slowly, but I found a workaround.
Instead of animating the Margin of the Path I animated the X value of a TranslateTransform on the Border object that contains the path.
I had to put the TranslateTransform in front of the ScaleTransform so that the translation was applied before the scale. That allows you to use almost the same values in your animation that you used for the Margin.
<Storyboard x:Key="MovingAnimation">
<ThicknessAnimationUsingKeyFrames RepeatBehavior="1:0:0" Storyboard.TargetName="_blank" Storyboard.TargetProperty="Margin" >
<LinearThicknessKeyFrame KeyTime="0:0:0" Value="-1.5,0,0,0" />
<LinearThicknessKeyFrame KeyTime="0:0:10" Value="1,0,0,0" />
<LinearThicknessKeyFrame KeyTime="0:0:20" Value="-1.5,0,0,0" />
</ThicknessAnimationUsingKeyFrames>
</Storyboard>
The ugly part is that I couldn't find a quick way to apply the values in the key frames directly to the X property of the TranslateTransform, so I cheated and used element binding and a placeholder Canvas object.
<StackPanel Grid.Row="0" Orientation="Horizontal" Margin="5">
<TextBlock Margin="0,0,5,0" Text="Margin.Left:"/>
<TextBlock Text="{Binding ElementName=_blank, Path=Margin.Left, StringFormat={}{0:0.#}}" />
</StackPanel>
<Canvas Name="_blank" /> <!--Placeholder object-->
<Canvas Name="_canvas" Grid.Row="1">
<Border Margin="0" Width="1" Height="1"
Name="_border"
VerticalAlignment="Center" HorizontalAlignment="Center">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform X="{Binding Margin.Left, ElementName=_blank}"/>
<ScaleTransform
ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}"
ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
CenterX="0"
CenterY="0">
</ScaleTransform>
</TransformGroup>
</Border.RenderTransform>
Even thought the animation is still being applied to a Margin and then to a TranslateTransform through element binding, the delay for a negative margin is gone.
I suspect that the negative margin delay has something to do with the Path being in the Border that was being scaled, but that is conjecture on my part.
If you can find a way to bind the KeyFrame values directly to the X property of the TranslateTransform, that would make this workaround much less ugly.
EDIT:
Figured out the proper binding to use:
<Storyboard x:Key="MovingAnimation2">
<DoubleAnimationUsingKeyFrames RepeatBehavior="1:0:0" Storyboard.TargetName="tt" Storyboard.TargetProperty="X" >
<LinearDoubleKeyFrame KeyTime="0:0:0" Value="-1.5" />
<LinearDoubleKeyFrame KeyTime="0:0:5" Value="1" />
<LinearDoubleKeyFrame KeyTime="0:0:10" Value="-1.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
This gets rid of the extra canvas placeholder object.
<Canvas Name="_canvas" Grid.Row="1">
<Border Margin="0" Width="1" Height="1"
Name="_border"
VerticalAlignment="Center" HorizontalAlignment="Center">
<Border.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="tt"/>
<ScaleTransform
ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}"
ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
CenterX="0"
CenterY="0">
</ScaleTransform>
</TransformGroup>
</Border.RenderTransform>
Animating Margin property will trigger additional measure/arrange pass which in turn cause a bit more performance impact (though in this example it may not be noticeable). Animation of "render-only" properties on the other hand will not trigger layout re-arrangement and, thus, is more performance friendly.
Please, take a look at a bit easier way to do what, I suppose, you are want to get:
<Window x:Class="Geometry.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="518" Width="530">
<Window.Resources>
<PathGeometry x:Key="MyGeometry">
<PathGeometry.Figures>
<PathFigure>
<PathFigure.Segments>
<LineSegment Point="0.30,0" />
<LineSegment Point="0.70,1" />
<LineSegment Point="0.40,1" />
<LineSegment Point="0,0" />
</PathFigure.Segments>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
<Storyboard x:Key="MovingAnimation">
<DoubleAnimationUsingKeyFrames RepeatBehavior="1:0:0" FillBehavior="HoldEnd" Storyboard.TargetName="_scaleTransform" Storyboard.TargetProperty="CenterX" >
<LinearDoubleKeyFrame KeyTime="0:0:0" Value="1.2" />
<LinearDoubleKeyFrame KeyTime="0:0:10" Value="-0.5" />
<LinearDoubleKeyFrame KeyTime="0:0:20" Value="1.2" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<BeginStoryboard Storyboard="{StaticResource MovingAnimation}" ></BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Label>Margin:</Label>
<TextBlock Text="{Binding ElementName=_scaleTransform, Path=CenterX, StringFormat={}{0:0.#}}" VerticalAlignment="Center" />
</StackPanel>
<!--
<Border Grid.Row="1" Margin="150" BorderBrush="Red" BorderThickness="1">
-->
<Grid Name="_canvas" Grid.Row="1">
<Path Name="_path" Fill="#CCCCFF" Data="{StaticResource MyGeometry}"
Width="1.0"
Height="1.0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Path.RenderTransform>
<ScaleTransform x:Name="_scaleTransform"
ScaleX="{Binding ElementName=_canvas, Path=ActualWidth}"
ScaleY="{Binding ElementName=_canvas, Path=ActualHeight}"
CenterX="1.2"
CenterY="0.5">
</ScaleTransform>
</Path.RenderTransform>
</Path>
</Grid>
<!--
</Border>
-->
</Grid>
</Window>
From the two answers so far, it's clear that if you want to have a shape fly around the screen, don't animate the margins.
Stewbob solved the problem by animating the X value of a translate transform.
sevenate solved the problem by animating the Center X value of a scale transform.
Another solution is, instead of wrapping the polygon in a border and animating the margin, wrap it up in a canvas and animate the left value.
Wrapping it in a canvas:
<Canvas Name="_canvasFrame" Grid.Row="1">
<Canvas Margin="0" Width="1" Height="1">
<Canvas.RenderTransform>
<ScaleTransform
ScaleX="{Binding ElementName=_canvasFrame, Path=ActualWidth}"
ScaleY="{Binding ElementName=_canvasFrame, Path=ActualHeight}"
CenterX="0"
CenterY="0">
</ScaleTransform>
</Canvas.RenderTransform>
<Path
Name="_path"
Fill="#CCCCFF"
Data="{StaticResource MyGeometry}"
Width="1.0" Height="1.0"
>
</Path>
</Canvas>
</Canvas>
Then animating the left value:
<Storyboard x:Key="MovingAnimation">
<DoubleAnimationUsingKeyFrames
RepeatBehavior="1:0:0"
FillBehavior="HoldEnd"
Storyboard.TargetName="_path"
Storyboard.TargetProperty="(Canvas.Left)" >
<DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="-1.0" />
<LinearDoubleKeyFrame KeyTime="0:0:10" Value="1.0" />
<LinearDoubleKeyFrame KeyTime="0:0:20" Value="-1.0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>

WPF Clip Rectangle

I have a UserControl that is 45x45 (hardcoded size - it's part of a grid of items). When a certain property has a value I want to show a "clip" in the upper right-hand corner indicating this. The visibility itself is easy to accomplish, however my Rectangle goes outside the bounds of the control and overlaps on other controls. I tried using the "ClipToBounds" property, but it didn't do anything. When I added that to the overall control the clip worked perfectly but my hover effects on the main rectangle (fills the cell) stopped working.
Any ideas? I'm confident this is simple to do, but still being pretty new to WPF (and horrible at geometry - hence not using the Polygon) I'm a bit lost.
Here is the full markup:
<Grid>
<Rectangle x:Name="MainRectangle" Fill="{Binding Background}" Opacity="0" MouseEnter="MainRectangle_MouseEnter" MouseLeave="MainRectangle_MouseLeave">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.0" To="0.8" Duration="0:0:0.33" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Rectangle.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" From="0.8" To="0.0" Duration="0:0:0.33" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding VisualCount}" />
<Rectangle Fill="Black" HorizontalAlignment="Right" Height="20" Margin="0,-14,-20,0" Stroke="Black" VerticalAlignment="Top" Width="20" Visibility="{Binding HasNotes}">
<Rectangle.RenderTransform>
<RotateTransform CenterX="0" CenterY="0" Angle="45" />
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
Here be a simple path:
<Path Fill="Black" HorizontalAlignment="Right" Visibility="{Binding HasNotes}">
<Path.Data>
<PathGeometry>
<PathFigure StartPoint="0,0">
<LineSegment Point="14,0"/>
<LineSegment Point="14,14"/>
</PathFigure>
</PathGeometry>
</Path.Data>
</Path>

WPF - Wait Animation on a separate thread?

(Note: I have seen this question and it uses a cursor not an animation.)
I have a wait animation (that I did not make but found on the internet). I want to show it while my app is doing some processing.
However, it gets stuck while my app is processing. Is there a way to make it keep going smooth? I usually think of a thread for this, but there are a few problems with that.
I have no idea how to fire off a thread in XAML
I usually know enough about threading to just get myself seriously messed up.
I have done very little threading code in .NET
Can any one help me out? Here is the XAML that creates the wait animation:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Viewbox Name="WaitCursor" >
<Canvas Width="80" Height="80" Name="canvas">
<Canvas.RenderTransform>
<RotateTransform Angle="0" CenterX="40" CenterY="40" />
</Canvas.RenderTransform>
<Canvas.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="canvas"
Storyboard.TargetProperty="(Canvas.RenderTransform).(RotateTransform.Angle)"
To="360"
Duration="0:0:0.7"
RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Canvas.Triggers>
<Ellipse Canvas.Top="0" Canvas.Left="30" Width="20" Height="20" >
<Ellipse.Fill>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color A="10" R="0" G="0" B="255" />
</SolidColorBrush.Color>
</SolidColorBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse Canvas.Top="10" Canvas.Left="50" Width="20" Height="20" Fill="#15000000"/>
<Ellipse Canvas.Top="30" Canvas.Left="60" Width="20" Height="20" Fill="#38000000"/>
<Ellipse Canvas.Top="50" Canvas.Left="50" Width="20" Height="20" Fill="#55000000"/>
<Ellipse Canvas.Top="60" Canvas.Left="30" Width="20" Height="20" Fill="#88000000"/>
<Ellipse Canvas.Top="50" Canvas.Left="10" Width="20" Height="20" Fill="#aa000000"/>
<Ellipse Canvas.Top="30" Canvas.Left="0" Width="20" Height="20" Fill="#cc000000"/>
<Ellipse Canvas.Top="10" Canvas.Left="10" Width="20" Height="20" Fill="#ff000000"/>
</Canvas>
</Viewbox>
</Grid>
</Page>
For those who need an actual code example, I plan to put this in the OnClick event of the "Link" Button found in this CodePlex Project.
Your best bet is to use a BackgroundWorker. It will do the work of marshaling to the correct thread on your behalf.

Resources