I am trying to convert "wipe" animation http://learnwpf.com/post/2006/10/03/How-can-I-create-a-e2809cwipee2809d-effect-to-transition-between-two-images-in-WPF.aspx sample to use it in C#.
So I did like:
<Grid>
<Image Source="C:\Temp\WMS\Others\megan_fox_17-normal.jpg" />
<Image Source="C:\Temp\WMS\Others\Hudgens.jpg">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Black" x:Name="BlackStop"/>
<GradientStop Offset="0" Color="Transparent" x:Name="TransparentStop"/>
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
<Button Content="Button" HorizontalAlignment="Left" Margin="72,288,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
</Grid>
and
private void Button_Click_1(object sender, RoutedEventArgs e)
{
var _doubleAnimationFrontPlayer = new DoubleAnimation();
_doubleAnimationFrontPlayer.By = 1;
_doubleAnimationFrontPlayer.Duration = new Duration(TimeSpan.FromSeconds(2));
sb.Children.Add(_doubleAnimationFrontPlayer);
Storyboard.SetTargetProperty(_doubleAnimationFrontPlayer, new PropertyPath(GradientStop.OffsetProperty));
Storyboard.SetTargetName(TransparentStop, "TransparentStop");
Storyboard.SetTarget(_doubleAnimationFrontPlayer, TransparentStop);
var _doubleAnimationFrontPlayer2 = new DoubleAnimation();
_doubleAnimationFrontPlayer2.By = 1;
_doubleAnimationFrontPlayer2.Duration = new Duration(TimeSpan.FromSeconds(2));
_doubleAnimationFrontPlayer2.BeginTime = TimeSpan.FromMilliseconds(1000) ;
sb.Children.Add(_doubleAnimationFrontPlayer2);
Storyboard.SetTargetProperty(_doubleAnimationFrontPlayer2, new PropertyPath(GradientStop.OffsetProperty));
Storyboard.SetTargetName(BlackStop, "BlackStop");
Storyboard.SetTarget(_doubleAnimationFrontPlayer2, BlackStop);
sb.Completed += sb_Completed;
sb.Begin();
}
void sb_Completed(object sender, EventArgs e)
{
Debug.WriteLine("DONE");
}
But nothing happens... :(
Any clue what is missing?
THANK YOU!
P.S. I found too late the same question here WPF Translating an XAML Animation to C# Code
So th ecorrect code I found here WPF Translating an XAML Animation to C# Code
I just edited it because I found 3 errors there:
public void WipeAnimation(FrameworkElement ObjectToAnimate)
{
LinearGradientBrush OpacityBrush = new LinearGradientBrush();
OpacityBrush.StartPoint = new Point(1, 0);
OpacityBrush.EndPoint = new Point(0, 0);
GradientStop BlackStop = new GradientStop(Colors.Black, 0);
GradientStop TransparentStop = new GradientStop(Colors.Transparent, 0);
OpacityBrush.GradientStops.Add(BlackStop);
OpacityBrush.GradientStops.Add(TransparentStop);
ObjectToAnimate.OpacityMask = OpacityBrush;
this.RegisterName("TransparentStop", TransparentStop);
this.RegisterName("BlackStop", BlackStop);
Duration d = TimeSpan.FromSeconds(4);
Storyboard sb = new Storyboard() { Duration = d };
DoubleAnimation DA = new DoubleAnimation() { By = 1, Duration = d };
DoubleAnimation DA2 = new DoubleAnimation() { By = 1, Duration = d };
sb.Children.Add(DA); sb.Children.Add(DA2);
Storyboard.SetTargetName(DA, "TransparentStop");
Storyboard.SetTargetName(DA2, "BlackStop");
Storyboard.SetTargetProperty(DA, new PropertyPath("Offset"));
Storyboard.SetTargetProperty(DA2, new PropertyPath("Offset"));
sb.Begin(this);
}
Author got +1 as well! :)
Related
I have a wpf app that I would like to allow the user to switch the 'Theme', which is simply the grid background.
This is the XAML:
<Grid x:Name="rabGrid">
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF080D39"/>
<GradientStop Color="White"/>
<GradientStop Color="#FF838589" Offset="1"/>
<GradientStop Color="#FF2E4999" Offset="0.997"/>
</LinearGradientBrush>
</Grid.Background>
Here's what I have in c#:
private void rTheme_Click(object sender, RoutedEventArgs e)
{
LinearGradientBrush rabThem = new LinearGradientBrush();
rabThem.StartPoint = new Point(0.5, 0);
rabThem.EndPoint = new Point(0.5, 1);
GradientStop rabThemStop = new GradientStop();
rabThemStop.Color = Color.FromArgb(100, 8, 13, 57);
GradientStop rabThemStop1 = new GradientStop();
rabThemStop1.Color = Colors.White;
GradientStop rabThemStop2 = new GradientStop();
rabThemStop2.Color = Color.FromArgb(100, 131, 133, 137);
rabThemStop2.Offset = 1;
GradientStop rabThemStop3 = new GradientStop();
rabThemStop3.Color = Color.FromArgb(100, 46, 73, 153);
rabThemStop3.Offset = .997;
}
My idea behind the above code is to setup all the metrics, then somehow fill to the background.
I have also tried variations like this with no joy:
clasGrid.Background = new LinearGradientBrush();
clasGrid.StartPoint = new Point(0.5, 0);
clasGrid.EndPoint = new Point(0.5, 1);
I'm can change the background with something like this:
clasGrid.Background = new LinearGradientBrush(Colors.LightBlue, Colors.SlateBlue, 90);
Implementing some of the syntax from the answer below, I've came up with this:
LinearGradientBrush rabThem = new LinearGradientBrush();
rabThem.EndPoint = new Point(0.5, 1);
rabThem.StartPoint = new Point(0.5, 0);
GradientStop rabThemStop = new GradientStop();
rabThemStop.Color = Color.FromArgb(100, 8, 13, 57);
GradientStop rabThemStop1 = new GradientStop();
rabThemStop1.Color = Colors.White;
GradientStop rabThemStop2 = new GradientStop();
rabThemStop2.Color = Color.FromArgb(100, 131, 133, 137);
rabThemStop2.Offset = 1;
GradientStop rabThemStop3 = new GradientStop();
rabThemStop3.Color = Color.FromArgb(100, 46, 73, 153);
rabThemStop3.Offset = .997;
rabThem.GradientStops.Add(rabThemStop);
rabThem.GradientStops.Add(rabThemStop1);
rabThem.GradientStops.Add(rabThemStop2);
rabThem.GradientStops.Add(rabThemStop3);
clasGrid.Background = rabThem;
While this works, the colors are a lot lighter (as if the gradient is not correct) and am still trying to figure that part out.
You have to set up the gradient each time. You can either make a method for it, or you can make a converter. I'm using a boolean to control which background is used, but you can use whatever value you want. If you choose to make a method, you can base it off of my converter.
public class OptionOrderBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// Create a background and return
bool b = (value != null ? (bool)value : false);
if (!b)
{
LinearGradientBrush lb = new LinearGradientBrush();
lb.StartPoint = new System.Windows.Point(0, 0);
lb.EndPoint = new System.Windows.Point(0, 1);
GradientStop gstop = new GradientStop(ViewModels.QuoteButtonStyle.Instance.QuoteButtonTopBackgroundColor, 0);
lb.GradientStops.Add(gstop);
gstop = new GradientStop(ViewModels.QuoteButtonStyle.Instance.QuoteButtonBottomBackgroundColor, 0.9);
lb.GradientStops.Add(gstop);
return lb;
}
else
{
LinearGradientBrush lb = new LinearGradientBrush();
lb.StartPoint = new System.Windows.Point(0, 0);
lb.EndPoint = new System.Windows.Point(0, 1);
GradientStop gstop = new GradientStop(Colors.Orange, 0);
lb.GradientStops.Add(gstop);
gstop = new GradientStop(Colors.WhiteSmoke, 0.9);
lb.GradientStops.Add(gstop);
return lb;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
For the converter, I bind it to the control like this:
Background="{Binding Path=IsDealable, FallbackValue=False, Converter={StaticResource OptionOrderBackgroundConverter}}"
If you use a converter and want to be able to pass in 2 colors, you can change it to an IMultiValueConverter.
In order to change a color of a rectangle in code behind I can use:
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "MyRectangle";
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
myRectangle.Fill = mySolidColorBrush;
SolidColorBrush blackBrush = new SolidColorBrush();
blackBrush.Color = Colors.Black;
myRectangle.StrokeThickness = 4;
myRectangle.Stroke = blackBrush;
ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.Red;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myColorAnimation);
myRectangle.MouseEnter += delegate(object sender, MouseEventArgs e)
{
myStoryboard.Begin(this);
};
myStackPanel.Children.Add(myRectangle);
this.Content = myStackPanel;
How can I do the same for the border of the rectangle (actually I'm looking more for a blinking-border effect than the fading one, maybe by changing Stroke property)?
Modify your Stroke:
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
myRectangle.Fill = mySolidColorBrush;
SolidColorBrush blackBrush = new SolidColorBrush(Colors.Black);
this.RegisterName("MySolidColorBorderBrush", blackBrush);
myRectangle.StrokeThickness = 4;
myRectangle.Stroke = blackBrush;
And storyboard setup
ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Black;
myColorAnimation.To = Colors.Blue;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBorderBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myColorAnimation);
Just for the archive (xaml)
<StackPanel Margin="20">
<Rectangle x:Name="MyRectangle" Width="100" Height="100" StrokeThickness="4">
<Rectangle.Fill>
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
</Rectangle.Fill>
<Rectangle.Stroke>
<SolidColorBrush x:Name="MySolidColorBorderBrush" Color="Black" />
</Rectangle.Stroke>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard Duration="0:0:1">
<ColorAnimation Storyboard.TargetName="MySolidColorBrush" Storyboard.TargetProperty="Color" From="Blue" To="Red" />
<ColorAnimation Storyboard.TargetName="MySolidColorBorderBrush" Storyboard.TargetProperty="Color" From="Black" To="Blue" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
I want change rectange color, but, color doesn't change. Where is problem?
ColorAnimation col = new ColorAnimation();
col.From = Colors.Aqua;
col.To = Colors.PaleGreen;
col.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard zgo = new Storyboard();
Storyboard.SetTarget(col, c);
Storyboard.SetTargetProperty(col,
new PropertyPath(SolidColorBrush.ColorProperty));
zgo.Children.Add(col);
zgo.Begin();
And here is XAML:
<Rectangle Name="rec"
Height="100" Width="200"
HorizontalAlignment="Left" VerticalAlignment="Top"
Stroke="Black"
MouseLeftButtonDown="rec_MouseLeftButtonDown">
<Rectangle.Fill>
<SolidColorBrush x:Name="c"></SolidColorBrush>
</Rectangle.Fill>
</Rectangle>
Run the animation directly by calling Animatable.BeginAnimation:
var colorAnimation = new ColorAnimation(
Colors.Aqua, Colors.PaleGreen, TimeSpan.FromSeconds(1));
c.BeginAnimation(SolidColorBrush.ColorProperty, colorAnimation);
You could still do it with a Storyboard by using the Rectangle as the animation's target and Fill.Color as target property::
Storyboard storyboard = new Storyboard();
Storyboard.SetTarget(colorAnimation, rec);
Storyboard.SetTargetProperty(colorAnimation, new PropertyPath("Fill.Color"));
storyboard.Children.Add(colorAnimation);
storyboard.Begin();
I found a great WIPE animation here : http://www.wearerighteous.com/programming/slidewipe-transition-for-your-windows-in-wpf/
EDIT: the link above is dead so you have to see this one
http://learnwpf.com/post/2006/10/03/How-can-I-create-a-e2809cwipee2809d-effect-to-transition-between-two-images-in-WPF.aspx
It has the same source code.
Basically, the code there is like this:
<Window.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0" Color="Black" x:Name="BlackStop"/>
<GradientStop Offset="0" Color="Transparent" x:Name="TransparentStop"/>
</LinearGradientBrush>
<Window.OpacityMask>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TransparentStop"
Storyboard.TargetProperty="Offset" By="1" Duration="0:0:1"/>
<DoubleAnimation Storyboard.TargetName="BlackStop"
Storyboard.TargetProperty="Offset" By="1" Duration="0:0:1"
BeginTime="0:0:0.05" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Window.Triggers>
I tried to "translate" the animation in c# code and I can't seem to do it. I tried several versions, like :
public void WipeAnimation(FrameworkElement ObjectToAnimate)
{
LinearGradientBrush OpacityBrush = new LinearGradientBrush();
OpacityBrush.StartPoint = new Point(1,0);
OpacityBrush.EndPoint = new Point(0,0);
GradientStop BlackStop = new GradientStop(Colors.Black, 0);
GradientStop TransparentStop = new GradientStop(Colors.Transparent, 0);
OpacityBrush.GradientStops.Add(t);
OpacityBrush.GradientStops.Add(t2);
ObjectToAnimate.OpacityMask = OpacityBrush;
Duration d = TimeSpan.FromSeconds(4);
Storyboard sb = new Storyboard() { Duration = d };
DoubleAnimation DA = new DoubleAnimation() { By=1 , Duration = d };
DoubleAnimation DA2 = new DoubleAnimation() { By=1 , Duration = d };
sb.Children.Add(DA); sb.Children.Add(DA2);
Storyboard.SetTarget(DA,TransparentStop);
Storyboard.SetTarget(DA2,BlackStop);
Storyboard.SetTargetProperty(DA, new PropertyPath("Offset"));
Storyboard.SetTargetProperty(DA2, new PropertyPath("Offset"));
sb.Begin();
}
Or replacing in the SetTarget Rows like :
Storyboard.SetTarget(DA, (ObjectToAnimate.OpacityMask as LinearGradientBrush).GradientStops[1]);
But nothing happens to my FrameworkElement. I called it for a Window (just like in the example from the site), and the only think that happens is that it sets the OpacityMask. The animation starts and ends (I added a Completed Event to the Storyboard with a MessageBox just to see if it works). I don't know what other things to do.
Please help! :(
Any ideas?
EDIT:
Maybe I explained the question bad. I'm trying to create the animation that I have in XAML, in C# code.... I've been trying for two days now, searching for a solution. I don't know why the C# version doesn't work ...
I'm not sure why the above is not working, but here's something that does work - instead of creating a Storyboard, simply use the BeginAnimation() method for each GradientStop:
BlackStop.BeginAnimation(GradientStop.OffsetProperty, DA2);
TransparentStop.BeginAnimation(GradientStop.OffsetProperty, DA);
public void WipeAnimation(FrameworkElement ObjectToAnimate)
{
LinearGradientBrush OpacityBrush = new LinearGradientBrush();
OpacityBrush.StartPoint = new Point(1,0);
OpacityBrush.EndPoint = new Point(0,0);
GradientStop BlackStop = new GradientStop(Colors.Black, 0);
GradientStop TransparentStop = new GradientStop(Colors.Transparent, 0);
OpacityBrush.GradientStops.Add(t);
OpacityBrush.GradientStops.Add(t2);
ObjectToAnimate.OpacityMask = OpacityBrush;
this.RegisterName("TransparentStop", TransparentStop);
this.RegisterName("BlackStop", BlackStop);
Duration d = TimeSpan.FromSeconds(4);
Storyboard sb = new Storyboard() { Duration = d };
DoubleAnimation DA = new DoubleAnimation() { By=1 , Duration = d };
DoubleAnimation DA2 = new DoubleAnimation() { By=1 , Duration = d };
sb.Children.Add(DA); sb.Children.Add(DA2);
Storyboard.SetTargetName(DA,"TransparentStop");
Storyboard.SetTargetName(DA2,"BlackStop");
Storyboard.SetTargetProperty(DA, new PropertyPath("Offset"));
Storyboard.SetTargetProperty(DA2, new PropertyPath("Offset"));
sb.Begin();
}
EDIT:
This code is great! But it has 3 errors so i found it. The correct version is here:
public void WipeAnimation(FrameworkElement ObjectToAnimate)
{
LinearGradientBrush OpacityBrush = new LinearGradientBrush();
OpacityBrush.StartPoint = new Point(1, 0);
OpacityBrush.EndPoint = new Point(0, 0);
GradientStop BlackStop = new GradientStop(Colors.Black, 0);
GradientStop TransparentStop = new GradientStop(Colors.Transparent, 0);
OpacityBrush.GradientStops.Add(BlackStop);
OpacityBrush.GradientStops.Add(TransparentStop);
ObjectToAnimate.OpacityMask = OpacityBrush;
this.RegisterName("TransparentStop", TransparentStop);
this.RegisterName("BlackStop", BlackStop);
Duration d = TimeSpan.FromSeconds(4);
Storyboard sb = new Storyboard() { Duration = d };
DoubleAnimation DA = new DoubleAnimation() { By = 1, Duration = d };
DoubleAnimation DA2 = new DoubleAnimation() { By = 1, Duration = d };
sb.Children.Add(DA); sb.Children.Add(DA2);
Storyboard.SetTargetName(DA, "TransparentStop");
Storyboard.SetTargetName(DA2, "BlackStop");
Storyboard.SetTargetProperty(DA, new PropertyPath("Offset"));
Storyboard.SetTargetProperty(DA2, new PropertyPath("Offset"));
sb.Begin(this);
}
Errors line are:
OpacityBrush.GradientStops.Add(t); -> OpacityBrush.GradientStops.Add(BlackStop);
OpacityBrush.GradientStops.Add(t2); -> OpacityBrush.GradientStops.Add(TransparentStop);
sb.Begin(); -> sb.Begin(this);
Seems to work great in my case.....
<Window x:Class="WpfHierarchicalDataGrid.Window4"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window4"
MinHeight="100"
MinWidth="100"
AllowsTransparency="True"
Opacity="0.7"
WindowState="Normal"
WindowStyle="None">
<Window.OpacityMask>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Offset="0" Color="Black"
x:Name="BlackStop"/>
<GradientStop Offset="0" Color="Transparent"
x:Name="TransparentStop"/>
</LinearGradientBrush>
</Window.OpacityMask>
<Window.Triggers>
<EventTrigger RoutedEvent="Window.Loaded">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="TransparentStop"
Storyboard.TargetProperty="Offset"
By="1" Duration="0:0:1"/>
<DoubleAnimation
Storyboard.TargetName="BlackStop"
Storyboard.TargetProperty="Offset" By="1"
Duration="0:0:1"
BeginTime="0:0:0.05" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Window.Triggers>
<Grid>
<Image Source="Water_lilies.jpg" Stretch="UniformToFill" />
</Grid>
</Window>
Why does Storyboard.SetTargetName works but Storyboard.SetTarget does not?
Here xaml -
<Grid Grid.Row="0" ClipToBounds="True">
<X:SmartContentControl x:Name="smartContent" Content="{Binding Path=MainContent}" ContentChanging="smartContent_ContentChanging">
<X:SmartContentControl.RenderTransform>
<TranslateTransform x:Name="translateTransformNew" X="0" Y="0"/>
</X:SmartContentControl.RenderTransform>
</X:SmartContentControl>
<ContentControl Content="{Binding ElementName=smartContent, Path=LastImage}">
<ContentControl.RenderTransform>
<TranslateTransform x:Name="translateTransformLast" X="0" Y="0"/>
</ContentControl.RenderTransform>
</ContentControl>
</Grid>
Here C#
private void smartContent_ContentChanging(object sender, RoutedEventArgs e)
{
Storyboard storyBoard = new Storyboard();
DoubleAnimation doubleAnimation1 = new DoubleAnimation(0.0, -smartContent.RenderSize.Width, new Duration(new TimeSpan(0, 0, 0, 0, 500)));
DoubleAnimation doubleAnimation2 = new DoubleAnimation(smartContent.RenderSize.Width, 0.0, new Duration(new TimeSpan(0, 0, 0, 0, 500)));
doubleAnimation1.AccelerationRatio = 0.5;
doubleAnimation2.DecelerationRatio = 0.5;
storyBoard.Children.Add(doubleAnimation1);
storyBoard.Children.Add(doubleAnimation2);
Storyboard.SetTarget(doubleAnimation1, this.translateTransformLast); //--- this does not work
//Storyboard.SetTargetName(doubleAnimation1, "translateTransformLast"); -- this works
Storyboard.SetTargetProperty(doubleAnimation1, new PropertyPath(TranslateTransform.XProperty));
Storyboard.SetTarget(doubleAnimation2, this.translateTransformNew);//--- this does not work
//Storyboard.SetTargetName(doubleAnimation2, "translateTransformNew"); -- this works
Storyboard.SetTargetProperty(doubleAnimation2, new PropertyPath(TranslateTransform.XProperty));
if (smartContent.LastImage != null)
storyBoard.Begin();
}
I found answer here!
Why don't these animations work when I'm using a storyboard?
Storyboard cant animate TranslateTransform, since it is not UIElement.
This is how i do it now! :)
Storyboard.SetTarget(doubleAnimation1, this.lastImage);
Storyboard.SetTargetProperty(doubleAnimation1, new PropertyPath("RenderTransform.(TranslateTransform.X)"));
Storyboard.SetTarget(doubleAnimation2, this.smartContent);
Storyboard.SetTargetProperty(doubleAnimation2, new PropertyPath("RenderTransform.(TranslateTransform.X)"));