I want to rotate Grid background image in WPF. I have animation code for image rotation. But when I implement in grid background, Image not accepted so Imagebrush only accepted.
<Grid.Background>
<ImageBrush ImageSource="../Images/1.jpg" Stretch="UniformToFill" TileMode="Tile"/>
</Grid.Background>
I can't implemented below animation code in WPF.
<Canvas ClipToBounds="True" >
<Image Source="/Images/1.jpg" Width="600" >
<Image.RenderTransform>
<RotateTransform x:Name="TransRotate" />
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
<BeginStoryboard>
<Storyboard TargetProperty="Angle">
<DoubleAnimation Storyboard.TargetName="TransRotate" Storyboard.TargetProperty="Angle" By="40" Duration="0:0:10" AutoReverse="True" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="TransRotate" Storyboard.TargetProperty="Angle" By="-40" Duration="0:0:15" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Canvas>
EDIT 1-
If I set the images as a content in grid, row 0 only show the image animation.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Canvas ClipToBounds="True" >
<Image Name="logo" Source="/Images/1.jpg" Width="800" >
<Image.RenderTransform>
<RotateTransform x:Name="TransRotate" />
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.Loaded">
<BeginStoryboard>
<Storyboard TargetProperty="Angle">
<DoubleAnimation Storyboard.TargetName="TransRotate" Storyboard.TargetProperty="Angle" By="40" Duration="0:0:10" AutoReverse="True" RepeatBehavior="Forever" />
<DoubleAnimation Storyboard.TargetName="TransRotate" Storyboard.TargetProperty="Angle" By="-40" Duration="0:0:15" AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Canvas>
<Border Grid.Row="0" Height="180" >
<Image Source="Images/01.jpg" Height="100" />
</Border>
<Border Grid.Row="1" Height="180">
<Image Source="Images/01.jpg" Height="100" />
</Border>
<Border Grid.Row="2" Height="180">
<Image Source="Images/01.jpg" Height="100" />
</Border>
</Grid>
You could rotate an ImageBrush like in the example below. You may also want to set the CenterX and CenterY properties of the RotateTransform.
<Grid>
<Grid.Background>
<ImageBrush ImageSource="C:\Users\Public\Pictures\Sample Pictures\Koala.jpg"
Stretch="UniformToFill">
<ImageBrush.Transform>
<RotateTransform/>
</ImageBrush.Transform>
</ImageBrush>
</Grid.Background>
<Grid.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Background.Transform.Angle"
By="40" Duration="0:0:10"
AutoReverse="True" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
</Grid>
As you figured out, Grid.Background can only take a Brush. A solution will be to add the Image as a child to the Grid control:
<Grid>
<Image ... />
... grid child elements ...
<Grid>
You will need to keep the Image element as the first child of the grid so that it will appear as grid background, and take care of possible additional problems (like ZOrder of the child elements, number of Grid row / columns, etc), but you should be able to obtain the effect you want.
Related
So I am trying to make an animation for a memory game project. The animation I am having trouble with is the flip animation. I have no problem making the image flip, but I want to make it change the image after the scale.x went from -1 to 0. This is what I have so far:
<Window.Resources>
<ControlTemplate TargetType="Button" x:Key="ImageButton">
<Image Source="gurbe1.jpg"
x:Name="image"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}" />
</ControlTemplate>
</Window.Resources>
<Grid>
<Button Template="{StaticResource ImageButton}"
Width="100" Click="Button_Click" RenderTransformOrigin="0.5,0.5">
<Button.RenderTransform>
<ScaleTransform x:Name="AnimatedScaleTransform" ScaleX="-1" />
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:1" Storyboard.TargetName="AnimatedScaleTransform" Storyboard.TargetProperty="(ScaleTransform.ScaleX)"/>
<DoubleAnimation To="1" BeginTime="0:0:1" Duration="0:0:1" Storyboard.TargetName="AnimatedScaleTransform" Storyboard.TargetProperty="(ScaleTransform.ScaleX)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
</Window>
I already looked on here and tried some stuff, but I couldn't get it to work :
xaml change image source
How can I do multiple animations in a single storyboard in C#/XAML?
For people also having this problem, it's as simple as this:
<Grid>
<Button Width="100" Click="Button_Click" RenderTransformOrigin="0.5,0.5" Height="100">
<Button.RenderTransform>
<ScaleTransform x:Name="AnimatedScaleTransform" ScaleX="-1" />
</Button.RenderTransform>
<Button.Template>
<ControlTemplate>
<Image Source="gurbe1.jpg"/>
</ControlTemplate>
</Button.Template>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="0" Duration="0:0:1" Storyboard.TargetName="AnimatedScaleTransform" Storyboard.TargetProperty="(ScaleTransform.ScaleX)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
<Button Width="100" Click="Button_Click" RenderTransformOrigin="0.5,0.5" Height="100">
<Button.RenderTransform>
<ScaleTransform x:Name="AnimatedScaleTransform2" ScaleX="0" />
</Button.RenderTransform>
<Button.Template>
<ControlTemplate>
<Image Source="gurbe2.jpg"/>
</ControlTemplate>
</Button.Template>
<Button.Triggers>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation From="0" To="1" BeginTime="0:0:2.3" Duration="0:0:1" Storyboard.TargetName="AnimatedScaleTransform2" Storyboard.TargetProperty="(ScaleTransform.ScaleX)"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</Grid>
It's not smooth atm, but you can get pretty close by adjusting the begin time
So I just got into animations and I wanted to do a "Slide out" animation and I managed to do so just fine.
But now I want it to slide in with the click on the same button.
So like I click it and it slides out and then I want it to slide back in when I click it again.
WITHOUT any code behind, so just through xaml
Here is the XAML
<Grid>
<Grid.Resources>
<Storyboard x:Key="TransformImage">
<DoubleAnimation
Storyboard.TargetName="MovingImage"
Storyboard.TargetProperty="(Image.RenderTransform).(TranslateTransform.X)"
By="130" Duration="0:0:0.3">
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="TransformButton">
<DoubleAnimation
Storyboard.TargetName="btnChange"
Storyboard.TargetProperty="(Button.RenderTransform).(TranslateTransform.X)"
By="130" Duration="0:0:0.3">
</DoubleAnimation>
</Storyboard>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btnChange">
<BeginStoryboard Storyboard="{StaticResource TransformImage}"/>
<BeginStoryboard Storyboard="{StaticResource TransformButton}"/>
</EventTrigger>
</Grid.Triggers>
<StackPanel Orientation="Horizontal" Margin="0">
<Image x:Name="MovingImage" Source="logo.png"
MaxWidth="120">
<Image.RenderTransform>
<TranslateTransform />
</Image.RenderTransform>
</Image>
</StackPanel>
<StackPanel
Panel.ZIndex="1"
Height="450"
Width="120"
HorizontalAlignment="Left"
Background="Black"></StackPanel>
<Button Margin="130,0,0,0" Height="40" Width="120"
Content="Show Image" x:Name="btnChange"
HorizontalAlignment="Left" >
<Button.RenderTransform>
<TranslateTransform />
</Button.RenderTransform>
</Button>
</Grid>
You need to store current state of slide animation when clicking on button and based on it run appropriate story board.
For example, you could use ToggleButton that has IsChecked property (or property in view-model).
To avoid duplicate triggers/styles I placed Image and ToggleButton in the same StackPanel.
<Grid>
<Grid.Resources>
<system:Double x:Key="SlideOffSet">130</system:Double>
<Storyboard x:Key="SlideRight">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
From="0" To="{StaticResource SlideOffSet}"
Duration="0:0:0.3" />
</Storyboard>
<Storyboard x:Key="SlideLeft">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
From="{StaticResource SlideOffSet}" To="0"
Duration="0:0:0.3" />
</Storyboard>
</Grid.Resources>
<StackPanel Orientation="Horizontal" Margin="0">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=SlideState}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource SlideRight}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource SlideLeft}" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<StackPanel.RenderTransform>
<TranslateTransform />
</StackPanel.RenderTransform>
<Image Source="logo.png" MaxWidth="120" />
<ToggleButton x:Name="SlideState" Margin="10,0,0,0" Height="40" Width="120" Content="Show Image" />
</StackPanel>
<StackPanel
Panel.ZIndex="1"
Height="450"
Width="120"
HorizontalAlignment="Left"
Background="Black"></StackPanel>
</Grid>
Also, I would not recommend using By property of the DoubleAnimation:
If animation is still running and you click button again, then second animation will be started at wrong position (it will use X value from first animation, which is not finished) - Click button quickly many times and you will see the problem.
Use From and To properties instead.
I created a simple notification window with animation and some message. But, can I disable animation or storyboard on eg. MouseEnter event, like a Facebook notification. Gradually reduced the opacity, and when I drag the Mouse on the window, then set opacity to 100%. How to do?
Here is a xaml code:
WindowStyle="None" AllowsTransparency="True" Background="Transparent" >
<Grid x:Name="gridData" RenderTransformOrigin="0,1" MouseRightButtonDown="Window_MouseRightButtonDown" MouseEnter="Grid_MouseEnter">
<Border BorderThickness="1" Background="SkyBlue" BorderBrush="Black" CornerRadius="10">
<StackPanel Margin="20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="txtTitle" Grid.Row="0" Grid.Column="0" Text="" FontWeight="Bold" VerticalAlignment="Center"/>
<Image x:Name="image" Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" Visibility="Collapsed"/>
<TextBlock x:Name="txtMessage" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Text="" TextWrapping="Wrap"/>
</Grid>
</StackPanel>
</Border>
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded" >
<BeginStoryboard >
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="0:0:2" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:4" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<Grid.RenderTransform>
<ScaleTransform ScaleY="1" />
</Grid.RenderTransform>
</Grid>
Add a name to your BeginStoryboard:
<BeginStoryboard Name="ScaleAndFadeOut">
then add another event trigger for a different event, and use a StopStoryboard element:
<Grid.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
...
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.MouseMove">
<StopStoryboard BeginStoryboardName="ScaleAndFadeOut" />
</EventTrigger>
</Grid.Triggers>
MSDN: "How to: Use Event Triggers to Control a Storyboard After It Starts"
I am creating a media player application and I am trying to animate hiding the controls when the mouse is not inside the program window.
I have a animation setup and working, but I can't think of how to set the EventTrigger to the parent grid rather than the grid I actually want to animate. Essentially I want to set the EventTrigger to be grdMain and animate the height of grdControls.
Animation:
<Window.Resources>
<Style x:Key="FadeInOut" TargetType="Grid">
<Style.Triggers>
<EventTrigger RoutedEvent="Control.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="40" Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Control.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
Grids:
<Grid x:Name="grdMain" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<MediaElement x:Name="meVideo" IsMuted="True" Stretch="Uniform" MediaOpened="meVideo_MediaOpened" MediaEnded="meVideo_MediaEnded" Grid.RowSpan="2" />
<Grid Grid.Row="1" >
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ProgressBar x:Name="pgbVideoTimeline" HorizontalAlignment="Stretch" Height="7" Background="#252525" Foreground="Maroon" BorderThickness="0" Grid.Row="1" MouseDown="pgbVideoTimeline_MouseDown" MouseMove="pgbVideoTimeline_MouseMove" MouseUp="pgbVideoTimeline_MouseUp" />
<Grid x:Name="grdControls" Grid.Row="2" Background="#0C0D0D" Height="0" Style="{StaticResource FadeInOut}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="stpPlaybackControls" Orientation="Horizontal" HorizontalAlignment="Left" Grid.Column="0">
<Image x:Name="btnPlayPause" Height="30" Margin="10,0,5,0" ToolTip="Play" Source="Resources/Images/UI/Play.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" MouseUp="btnPlayPause_MouseUp" />
<Image x:Name="btnReplay" Height="20" Margin="5,0,5,0" ToolTip="Replay" Source="Resources/Images/UI/Replay.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" MouseUp="btnReplay_MouseUp" />
</StackPanel>
<StackPanel x:Name="stpMiscControls" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1">
<Image x:Name="btnFullScreen" Height="25" Margin="5" ToolTip="Fullscreen" Source="Resources/Images/UI/FullScreen.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" MouseUp="btnFullScreen_MouseUp" />
<Image x:Name="btnSettings" Height="30" Margin="5,5,10,5" ToolTip="Settings" Source="Resources/Images/UI/Settings.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" />
</StackPanel>
</Grid>
</Grid>
</Grid>
The rule when using Trigger (in case TargetName can't be used) is the Trigger should belong to the element which has the properties you want to modify. In this case the Trigger should belong to the grdControls. However you can use DataTrigger to walk up the tree and listen to some other property change of any visual upwards in the tree. The following code should work:
<Style x:Key="FadeInOut" TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=grdMain}"
Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="40"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="0"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
The second approach close to what Peter Dunno suggested in his comment requires you to have to set the EventTrigger directly in the Triggers property of the main Grid. You can either set the Storyboards directly or define them as Resource. Here is the code for that approach:
<Grid x:Name="grdMain" Background="Black">
<Grid.Triggers>
<EventTrigger RoutedEvent="Control.MouseEnter">
<BeginStoryboard>
<Storyboard TargetName="grdControls">
<DoubleAnimation Duration="0:0:1" To="40"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Control.MouseLeave">
<BeginStoryboard>
<Storyboard TargetName="grdControls">
<DoubleAnimation Duration="0:0:1" To="0"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<!-- remaining code -->
</Grid>
Note that the Style you define now is no longer needed.
I'm pretty new to WPF and even newer to animations in WPF. I know there are storyboards, etc. But I'm looking for a specific effect so I can work from there and tinker with it.
Can anyone just give me a simple example about on Image control MouseDown (because there is no Click event in this control in WPF) makes the image bigger through a nifty looking animation?
Thanks bros.
The following will scale the image relative to it's current size, rather than changing the absolute values. This might be more flexible.
<Page xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Image x:Name="MyImage" Source="c:\myImage.jpg" Width="250" Height="250">
<Image.RenderTransform>
<ScaleTransform x:Name="ImageScale" ScaleX="1" ScaleY="1" RenderTransformOrigin="0.5, 0.5"/>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ImageScale" Storyboard.TargetProperty="(ScaleTransform.ScaleX)" To="1.5" Duration="0:0:0.25" AutoReverse="True"/>
<DoubleAnimation Storyboard.TargetName="ImageScale" Storyboard.TargetProperty="(ScaleTransform.ScaleY)" To="1.5" Duration="0:0:0.25" AutoReverse="True"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Image.Triggers>
</Image>
</Page>
Here is an example that does what I think you want:
<Window x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Window.Resources>
<Storyboard x:Key="ScaleImageStoryboard">
<DoubleAnimation Duration="0:0:0.5" From="300" To="400" Storyboard.TargetName="Image" Storyboard.TargetProperty="Height"/>
<DoubleAnimation Duration="0:0:0.5" From="300" To="400" Storyboard.TargetName="Image" Storyboard.TargetProperty="Width"/>
</Storyboard>
</Window.Resources>
<Grid>
<Image Name="Image" Source="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg" Stretch="Fill" Width="300" Height="300">
<Image.Triggers>
<EventTrigger RoutedEvent="Image.MouseDown">
<BeginStoryboard Storyboard="{StaticResource ScaleImageStoryboard}"/>
</EventTrigger>
</Image.Triggers>
</Image>
</Grid>
</Window>
Here, the image starts off at 300x300 px. When the Image.MouseDown event is fired the Trigger begins the storyboard which changes the image size to 400x400 over a half second period.
However, if you wanted an effect that just affected the size of the image temporarily and didn't influence layout, you would use:
<Window x:Class="WpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="600" Width="600">
<Window.Resources>
<Storyboard x:Key="ScaleImageStoryboard">
<DoubleAnimation Duration="0:0:0.2" From="1" To="1.2" AutoReverse="True"
Storyboard.TargetName="ScaleImage" Storyboard.TargetProperty="ScaleX"/>
<DoubleAnimation Duration="0:0:0.2" From="1" To="1.2" AutoReverse="True"
Storyboard.TargetName="ScaleImage" Storyboard.TargetProperty="ScaleY"/>
</Storyboard>
</Window.Resources>
<Grid>
<Image Name="Image" Source="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg"
Stretch="Fill" Width="300" Height="300"
RenderTransformOrigin="0.5, 0.5">
<Image.RenderTransform>
<ScaleTransform x:Name="ScaleImage"/>
</Image.RenderTransform>
<Image.Triggers>
<EventTrigger RoutedEvent="Image.MouseDown">
<BeginStoryboard Storyboard="{StaticResource ScaleImageStoryboard}"/>
</EventTrigger>
</Image.Triggers>
</Image>
</Grid>
</Window>