silverlight animation question - silverlight

Doe's anybody knows what wrong with markup below
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="DoubleAnim.MainPage"
Width="640" Height="480">
<UserControl.Resources>
<Storyboard x:Name="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(Canvas.Left)" Storyboard.TargetName="objectToAnimate">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="400"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Rectangle x:Name="objectToAnimate" Fill="#FF0000F9" HorizontalAlignment="Left" Canvas.Top="164" Height="100" Stroke="Black" VerticalAlignment="Top" Width="192" RadiusY="8" RadiusX="8" >
</Rectangle>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="132,180,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
</UserControl>
Everything looks good but it not works:((
Doe's silverlight know how to animate canvas.top and canvas.left?
Or maybe that I have missed something?

You need a canvas object. Replace Grid with Canvas.

The Canvas.Top and Canvas.Left attached properties are only used if the Rectangle (or UIElement) is hosted in a Canvas panel. The Grid uses different logic and attached properties to layout it's children.

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.

Win Form user control not visible in WPF xaml

I have a xaml start up form in which I am trying to host a windows form control which is a splash screen displaying Product Name / License stuff.. Here is the xaml code which I am using to host the user control but its not at all visible. Not in the designer nor when I run the application actually... Whats wrong in this?
<Window
x:Class="StartupWindow"
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:wf="clr-namespace:namespace;assembly=assemblyName"
mc:Ignorable="d" x:Name="splashWindow"
WindowStyle="None" ResizeMode="NoResize" Width="500" Height="400"
AllowsTransparency="True" Background="Transparent" ShowInTaskbar="False" Topmost="True"
>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Unloaded">
<BeginStoryboard>
<Storyboard x:Name="board">
<DoubleAnimation Storyboard.TargetName="splashWindow" Storyboard.TargetProperty="Opacity" From="1.0" To="0" Duration="0:0:1.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Grid x:Name="Splash" Width="450" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,100,0,0">
<Grid x:Name="Back">
<Grid.Effect>
<DropShadowEffect ShadowDepth="1" Direction="-90" BlurRadius="10" Opacity="0.25"/>
</Grid.Effect>
<Border Background="Black" CornerRadius="3" Opacity="0.15"/>
<Border CornerRadius="2" Margin="1" Background="#229C47"/>
</Grid>
<Grid x:Name="Content_Area" Margin="12">
<Image x:Name="Image" Stretch="None" Height="99" Grid.Row="1"/>
<TextBlock x:Name="Info" TextWrapping="Wrap" Text="Starting..." Grid.Row="2" Margin="12,12,12,0" Foreground="White"/>
</Grid>
</Grid>
<WindowsFormsHost Height="325" Name="splashControl" Margin="54,12,64,24" Width="460" HorizontalAlignment="Center" Background="Transparent">
<wf:SplashControl />
</WindowsFormsHost>
</Grid>
</Window>
I'm fighting with the same problem now.
The problem here is the AllowsTransparency="True" of the window, that is incompatible with showing WinForms controls with WindowsFormsHost.
Take a look here.

Animate Insertions to ItemsControl

I'm finding WPF inscrutable at times. Given the following XAML how would one add triggers to animate (slide down, fade in) new items added to the ObservableCollection Timeline. I've seen various examples for list boxes but nothing for items control.
<Grid>
<ScrollViewer>
<ItemsControl Name="TimelineItem"
ItemsSource="{Binding Timeline}"
Style="{StaticResource TimelineStyle}"
ItemContainerStyle="{StaticResource TweetItemStyle}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid VerticalAlignment="Top"
HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Style="{StaticResource TweetImageColumnStyle}" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Grid.Column="0"
Style="{StaticResource TweetImageStyle}">
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding ProfileImageUrl}" />
</Rectangle.Fill>
</Rectangle>
<StackPanel Grid.Column="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Style="{StaticResource TweetNameStyle}"
Text="{Binding Name}" />
<TextBlock Grid.Column="1"
Style="{StaticResource TweetTimeStyle}"
Text="{Binding TimeAgo}" />
</Grid>
<Controls:TextBlockMarkup Grid.Row="1"
Grid.Column="1"
Markup="{Binding MarkupText}"
Style="{StaticResource TweetStyle}" />
</StackPanel>
<Separator Grid.Row="2"
Grid.ColumnSpan="2"
Style="{StaticResource TweetSeparatorTop}" />
<Separator Grid.Row="3"
Grid.ColumnSpan="2"
Style="{StaticResource TweetSeparatorBottom}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
It's been a while since I've animated WPF, but this should work by setting a DataTrigger in the DataTemplate of the ItemsControl for the Loaded Event.
A couple of notes:
Add the following xaml to the DataTemplate of the ItemsControl
Name the <Grid> inside the DataTemplate: "MyGrid"
Add a RenderTransformOriginproperty to the MyGrid to set the Y origin at the top:
<Grid x:Name="MyGrid" RenderTransformOrigin="0.5,0">
Be sure to include the Grid.RenderTransform attached property to your grid (see sample below)
Xaml
<DataTemplate.Resources>
<Storyboard x:Key="ItemAnimation" AutoReverse="False">
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyGrid" Storyboard.TargetProperty="(UIElement.Opacity)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyGrid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<EasingDoubleKeyFrame KeyTime="0" Value="0" />
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</DataTemplate.Resources>
<DataTemplate.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource ItemAnimation}" />
</EventTrigger>
</DataTemplate.Triggers>
Add the RenderTransform groups to your Grid
<!-- Include in the Grid -->
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
</TransformGroup>
</Grid.RenderTransform>
This should get you close enough so that you can customize it yourself. FWIW: I used Blend to build out the animation by editing the style of the ItemTemplate of the Timeline object.
One last note: The animation will occur when the window loads the ItemsControl for the first time, for each item in the original collection. And will occur for an individual item when it is added to the collection. This behavior is a bit wonky, so you could remove the explicit binding of the trigger in the xaml and bind the trigger in the code-behind after the ItemsControl or Window loads.
EDIT
I've updated the example so that it should work with your XAML now.
Added another animation to slide (sort of) the new item. Actually, it's growing from a size of 0% to 100%, starting from the top of the Y axis.
Revised note #3 from above to include a RenderTransformOrigin property.
Added note #4 to include the Grid.RenderTransform attached property.

Modify Silverlight Resource in VisualState

I am wondering if there is an easy way to modify some kind of shared resource (i.e. a Brush) of a control between different VisualStates. For example, I would like to define a Brush to use as both the Background of a Border and the Fill of a different Rectangle. In a different VisualState I would like to change this background Brush in one place (the resource) and have it reflected in all elements using the resource.
I am not sure if resources can really be referenced by Name (not Key) for the TargetName of the Storyboard in the VisualState.
Here is a simplified example of what I am trying to do in XAML:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SilverlightApplication.MainPage"
Width="200" Height="200">
<UserControl.Resources>
<SolidColorBrush x:Name="Background" x:Key="Background" Color="Black" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Red">
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="Background" Storyboard.TargetProperty="(Color)">
<EasingColorKeyFrame KeyTime="00:00:00" Value="Red"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border Background="{StaticResource Background}" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Red" BorderThickness="1"/>
<Rectangle Fill="{StaticResource Background}" Width="100" Height="100" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
</Grid>
</UserControl>
I have a feeling because these are StaticResources in Silverlight they are only loaded once and can not be changed. I know WPF has some concept of DynamicResources. Is there any way to achieve this type of behavior in Silverlight without having to redefine my brush in all elements?
DynamicResources unfortunately don't exist in Silverlight.
Some people use Bindings.
There's a sneaky way to simulate the experience within a single UserControl that you might want to try.
All that's happening in the code below is that the Storyboard animates a single rectangle's Fill, which is then bound to the other Fill's in the UserControl by using Element binding. The source rectangle doesn't need to be visible for this to work.
<UserControl x:Class="TestSilverlightStuff.MainPage"
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:TestSilverlightStuff"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<SolidColorBrush x:Key="Background" Color="Black" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MyStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Red">
<Storyboard>
<ColorAnimation Duration="0" To="Red" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="trickyRectangle" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle Fill="Black" x:Name="trickyRectangle" Visibility="Collapsed" />
<Border Background="{Binding Fill, ElementName=trickyRectangle}" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top" BorderBrush="Red" BorderThickness="1"/>
<Rectangle Fill="{Binding Fill, ElementName=trickyRectangle}" Width="100" Height="100" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
<Button Content="Button" Height="57" HorizontalAlignment="Left" Margin="12,231,0,0" Name="button1" VerticalAlignment="Top" Width="153" Click="button1_Click" />
</Grid>
</UserControl>
Here's the C# button click code:
private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
VisualStateManager.GoToState(this, "Red", true);
}
It's not as elegant as a DynamicResource, but it works in some cases.

Resources