How to create multiple parallel animations to the same element? - wpf

I'm trying to set multiple parallel animations for the same element in code-behind. Well, when im trying to pull "Moving" (RenderTransorm.X + Y) and Opacity together, it runs perfect. But when im trying to add scale animation or Width-Height animation, only the latest animation is running.
What im i doing wrong? - or, is there any elegant way to do this programmatically?
private void StartAnimation(TimeSpan startOffsetTime, TimeSpan duration)
{
if (TweetIsAnimated)
{
Globals.IsAnimating = true;
}
if (_hasAnimated)
{
return;
}
_hasAnimated = true;
StopAnimation();
EnsureTransform();
var storyboard = new Storyboard();
//--------------------------HORIZONTAL ANIMATION-------------------------
if (MoveStory)
{
var horizontalAnimation = new DoubleAnimation(FromHorizontalOffset, 0, duration)
{
EasingFunction = GetFuncByName(EasingFuncType)
//new CubicEase { EasingMode = EasingMode.EaseOut }
};
storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
storyboard.Children.Add(horizontalAnimation);
Storyboard.SetTarget(horizontalAnimation, AssociatedObject);
Storyboard.SetTargetProperty(horizontalAnimation, new PropertyPath("RenderTransform.X"));
storyboard.BeginTime = startOffsetTime;
storyboard.Begin();
}
//------------------------------------------------------------------------
//--------------------------VERTICAL ANIMATION----------------------------
if (MoveStory)
{
var veritcalAnimation = new DoubleAnimation(FromVerticalOffset, 0, duration)
{
EasingFunction = GetFuncByName(EasingFuncType)
};
storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
storyboard.Children.Add(veritcalAnimation);
Storyboard.SetTarget(veritcalAnimation, AssociatedObject);
Storyboard.SetTargetProperty(veritcalAnimation, new PropertyPath("RenderTransform.Y"));
storyboard.BeginTime = startOffsetTime;
storyboard.Begin();
}
//------------------------------------------------------------------------
//--------------------------OPACITY ANIMATION-----------------------------
if (OpacityStory)
{
var opacityAnimation = new DoubleAnimationUsingKeyFrames();
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(OpacityStart, TimeSpan.Zero));
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(OpacityStart, startOffsetTime,
GetFuncByName(EasingFuncType)));
opacityAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1,
duration + startOffsetTime +
TimeSpan.FromMilliseconds(
Duration.TotalMilliseconds/2),
GetFuncByName(EasingFuncType)));
storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
storyboard.Children.Add(opacityAnimation);
Storyboard.SetTarget(opacityAnimation, AssociatedObject);
Storyboard.SetTargetProperty(opacityAnimation, new PropertyPath(UIElement.OpacityProperty));
storyboard.Begin();
}
//------------------------------------------------------------------------
//--------------------------SCALE ANIMATION------------------------------
if (ScaleStory)
{
ScaleTransform scaleTransform1 = new ScaleTransform(1, 1, AssociatedObject.ActualWidth, AssociatedObject.ActualHeight);
AssociatedObject.RenderTransformOrigin = new Point(1, ScaleStart);
AssociatedObject.RenderTransform = scaleTransform1;
var EasingFunction1 = new BackEase() { EasingMode = EasingMode.EaseOut, Amplitude = AmplitudeNow };
var scaleAnimation = new DoubleAnimationUsingKeyFrames();
TimeSpan time = duration + startOffsetTime + TimeSpan.FromMilliseconds(Duration.TotalMilliseconds / 2);
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(ScaleStart, TimeSpan.Zero));
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(ScaleStart, startOffsetTime, EasingFunction1));
scaleAnimation.KeyFrames.Add(new EasingDoubleKeyFrame(1, time, EasingFunction1));
storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
storyboard.Children.Add(scaleAnimation);
Storyboard.SetTarget(scaleAnimation, AssociatedObject);
Storyboard.SetTargetProperty(scaleAnimation, new PropertyPath("RenderTransform.ScaleY"));
storyboard.Begin();
}
//------------------------------------------------------------------------
//--------------------------RESIZE ANIMATION------------------------------
if (ResizeStory)
{
DoubleAnimation widthAnimation = new DoubleAnimation
{
From = WidthStart,
To = AssociatedObject.ActualWidth,
Duration = Duration
};
DoubleAnimation heightAnimation = new DoubleAnimation
{
From = HeightStart,
To = AssociatedObject.ActualHeight,
Duration = Duration
};
storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
storyboard.Children.Add(widthAnimation);
Storyboard.SetTarget(widthAnimation, AssociatedObject);
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(FrameworkElement.WidthProperty));
storyboard.BeginTime = startOffsetTime;
storyboard.Begin();
storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
storyboard.Children.Add(heightAnimation);
Storyboard.SetTarget(heightAnimation, AssociatedObject);
Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(FrameworkElement.HeightProperty));
storyboard.BeginTime = startOffsetTime;
storyboard.Begin();
}
//------------------------------------------------------------------------
}

Do not create new storyboard!
Refactor your code like this:
var storyboard = new Storyboard();
storyboard.Completed += AnimationOnCompleted;
_storyboards.Add(storyboard, true);
if (MoveStory)
{
var horizontalAnimation = new DoubleAnimation(FromHorizontalOffset, 0, duration)
{
EasingFunction = GetFuncByName(EasingFuncType)
//new CubicEase { EasingMode = EasingMode.EaseOut }
};
storyboard.Children.Add(horizontalAnimation);
Storyboard.SetTarget(horizontalAnimation, AssociatedObject);
Storyboard.SetTargetProperty(horizontalAnimation, new PropertyPath("RenderTransform.X"));
}
// ... if else etc...
if (ResizeStory)
{
DoubleAnimation widthAnimation = new DoubleAnimation
{
From = WidthStart,
To = AssociatedObject.ActualWidth,
Duration = Duration
};
DoubleAnimation heightAnimation = new DoubleAnimation
{
From = HeightStart,
To = AssociatedObject.ActualHeight,
Duration = Duration
};
storyboard.Children.Add(widthAnimation);
Storyboard.SetTarget(widthAnimation, AssociatedObject);
Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(FrameworkElement.WidthProperty));
storyboard.Children.Add(heightAnimation);
Storyboard.SetTarget(heightAnimation, AssociatedObject);
Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(FrameworkElement.HeightProperty));
}
storyboard.BeginTime = startOffsetTime;
storyboard.Begin();

Related

Animation in codebehind for loop, using RenderTransform

Is it possible to animate the "old school" way, in codebehind, instead of xaml?
I just want an arrow that points to something with a 'bounce effect' which I could easily do in my own for loop. But I do not know how to refresh or do a timer delay, inside the loop. I already placed the image into position in codebehind. All I want to do is this simple animation...
public void validationArrow()
{
var validationArrow = new Image();
validationArrow.Source = new BitmapImage(new Uri("/SlProject;component/arrow.png", UriKind.RelativeOrAbsolute));
LayoutRoot.Children.Add(validationArrow);
validationArrow.Stretch = Stretch.None;
validationArrow.VerticalAlignment = System.Windows.VerticalAlignment.Top;
validationArrow.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
var arrowPosition = new TranslateTransform { X = 0, Y = 0 };
validationArrow.RenderTransform = arrowPosition;
validationArrow.Name = "validationArrow";
for (int i = 150; i >= 0; i--)
{
arrowPosition.X = i;
validationArrow.RenderTransform = arrowPosition;
// how can I refresh screen and do some timing here?
}
}
There's no school like the old school ;)
Here, this should help you on your way. You can play with the millisecond and Y translation values being passed to the BuildEasing method to change the 'bounce' effect's speed and distance.
private void RunStoryboard()
{
var arrowImage = new Image();
arrowImage.RenderTransform = new CompositeTransform();
arrowImage.Source = new BitmapImage(new Uri("/SlProject;component/arrow.png", UriKind.RelativeOrAbsolute));
LayoutRoot.Children.Add(arrowImage);
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(BuildKeyFrame(arrowImage));
storyboard.Begin();
}
private DoubleAnimationUsingKeyFrames BuildKeyFrame(Image target)
{
DoubleAnimationUsingKeyFrames kf = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(kf, target);
Storyboard.SetTargetProperty(kf, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
kf.KeyFrames.Add(BuildEasing(100, 10));
kf.KeyFrames.Add(BuildEasing(200, 0));
kf.KeyFrames.Add(BuildEasing(300, 10));
kf.KeyFrames.Add(BuildEasing(400, 0));
kf.KeyFrames.Add(BuildEasing(500, 10));
kf.KeyFrames.Add(BuildEasing(600, 0));
return kf;
}
private EasingDoubleKeyFrame BuildEasing(int ms, int value)
{
return new EasingDoubleKeyFrame()
{
KeyTime = KeyTime.FromTimeSpan(new TimeSpan(0, 0, 0, 0, ms)),
Value = value
};
}

Animation target not specified issue - Silverlight storyboards

Having some real head scratching going on here as I can't seem to think why I am getting the Animation target not specified error. I create a static class for dishing out storyboards of lots of little fires "burning". I then create as many of those fires as the user wants and assign a new storyboard to it, all in Csharp. I then begin then storyboard, but as I say, I keep getting this error and I can't seem why. Here is the storyboard creating class, and when I try to call it.
public static class FireStoryboard
{
public static Storyboard fireStoryboard(UIElement target)
{
Storyboard s = new Storyboard();
s.RepeatBehavior = RepeatBehavior.Forever;
DoubleAnimationUsingKeyFrames scaleY = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(scaleY, target);
scaleY.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleY)"));
EasingDoubleKeyFrame e1 = new EasingDoubleKeyFrame();
e1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
e1.Value = 1.8;
e1.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame e2 = new EasingDoubleKeyFrame();
e2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
e1.Value = 1;
e2.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
scaleY.KeyFrames.Add(e1);
scaleY.KeyFrames.Add(e2);
DoubleAnimationUsingKeyFrames translateY = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(translateY, target);
translateY.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.TranslateY)"));
EasingDoubleKeyFrame e3 = new EasingDoubleKeyFrame();
e3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
e3.Value = -4;
e3.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame e4 = new EasingDoubleKeyFrame();
e4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
e4.Value = 0;
e4.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
translateY.KeyFrames.Add(e3);
translateY.KeyFrames.Add(e4);
DoubleAnimationUsingKeyFrames opacity = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(opacity, target);
opacity.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("UIElement.Opacity"));
EasingDoubleKeyFrame e5 = new EasingDoubleKeyFrame();
e5.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
e5.Value = 0.7;
EasingDoubleKeyFrame e6 = new EasingDoubleKeyFrame();
e6.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
e6.Value = 1;
EasingDoubleKeyFrame e7 = new EasingDoubleKeyFrame();
e7.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
e7.Value = 0.7;
opacity.KeyFrames.Add(e5);
opacity.KeyFrames.Add(e6);
opacity.KeyFrames.Add(e7);
DoubleAnimationUsingKeyFrames shadowDirection = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowDirection, target);
shadowDirection.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Direction)"));
EasingDoubleKeyFrame eShad1 = new EasingDoubleKeyFrame();
eShad1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eShad1.Value = 449;
EasingDoubleKeyFrame eShad2 = new EasingDoubleKeyFrame();
eShad2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eShad2.Value = 449;
shadowDirection.KeyFrames.Add(eShad1);
shadowDirection.KeyFrames.Add(eShad2);
DoubleAnimationUsingKeyFrames shadowDepth = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowDepth, target);
shadowDirection.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.ShadowDepth)"));
EasingDoubleKeyFrame eShad3 = new EasingDoubleKeyFrame();
eShad3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eShad3.Value = 0;
EasingDoubleKeyFrame eShad4 = new EasingDoubleKeyFrame();
eShad4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eShad4.Value = 5;
EasingDoubleKeyFrame eShad5 = new EasingDoubleKeyFrame();
eShad5.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
eShad5.Value = 20;
shadowDirection.KeyFrames.Add(eShad3);
shadowDirection.KeyFrames.Add(eShad4);
shadowDirection.KeyFrames.Add(eShad5);
DoubleAnimationUsingKeyFrames shadowOpacity = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowOpacity, target);
shadowDirection.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Opacity)"));
EasingDoubleKeyFrame eShad6 = new EasingDoubleKeyFrame();
eShad6.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eShad6.Value = 1;
EasingDoubleKeyFrame eShad7 = new EasingDoubleKeyFrame();
eShad7.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
eShad7.Value = 0;
shadowDirection.KeyFrames.Add(eShad6);
shadowDirection.KeyFrames.Add(eShad7);
DoubleAnimationUsingKeyFrames skewX = new DoubleAnimationUsingKeyFrames();
Storyboard.SetTarget(skewX, target);
skewX.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.SkewX)"));
EasingDoubleKeyFrame eSkew1 = new EasingDoubleKeyFrame();
eSkew1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eSkew1.Value = 0;
eSkew1.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew2 = new EasingDoubleKeyFrame();
eSkew2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
eSkew2.Value = -5;
eSkew2.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew3 = new EasingDoubleKeyFrame();
eSkew3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1));
eSkew3.Value = 5;
eSkew3.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew4 = new EasingDoubleKeyFrame();
eSkew4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.5));
eSkew4.Value = -5;
eSkew4.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
EasingDoubleKeyFrame eSkew5 = new EasingDoubleKeyFrame();
eSkew5.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(2));
eSkew5.Value = 0;
eSkew5.EasingFunction = new BounceEase() { EasingMode = System.Windows.Media.Animation.EasingMode.EaseInOut };
skewX.KeyFrames.Add(eSkew1);
skewX.KeyFrames.Add(eSkew2);
skewX.KeyFrames.Add(eSkew3);
skewX.KeyFrames.Add(eSkew4);
skewX.KeyFrames.Add(eSkew5);
ColorAnimationUsingKeyFrames shadowColor = new ColorAnimationUsingKeyFrames();
Storyboard.SetTarget(shadowColor, target);
shadowColor.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("(UIElement.Effect).(DropShadowEffect.Color)"));
EasingColorKeyFrame eColor1 = new EasingColorKeyFrame();
eColor1.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0));
eColor1.Value = Colors.Red;
EasingColorKeyFrame eColor2 = new EasingColorKeyFrame();
eColor2.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.5));
eColor2.Value = Color.FromArgb(255, 254, 31, 0);
EasingColorKeyFrame eColor3 = new EasingColorKeyFrame();
eColor3.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.7));
eColor3.Value = Color.FromArgb(255, 254, 255, 0);
EasingColorKeyFrame eColor4 = new EasingColorKeyFrame();
eColor4.KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.8));
eColor4.Value = Colors.Black;
shadowColor.KeyFrames.Add(eColor1);
shadowColor.KeyFrames.Add(eColor2);
shadowColor.KeyFrames.Add(eColor3);
shadowColor.KeyFrames.Add(eColor4);
s.Children.Add(scaleY);
s.Children.Add(translateY);
s.Children.Add(opacity);
s.Children.Add(shadowDirection);
s.Children.Add(shadowDepth);
s.Children.Add(shadowOpacity);
s.Children.Add(skewX);
s.Children.Add(shadowColor);
Storyboard.SetTarget(s, target);
return s;
}
}
And here is where I assign it to each fire image:
Storyboard fireStoryboard = FireStoryboard.fireStoryboard(fire);
fireStoryboard.Begin();
Any help would be greatly appreciated. Am I missing setting a target somewhere? I really cannot see where :(.
The following works fine for me when the elementName x:Name can be found in the element which has the Storyboard in it's resources. When implementing MVVM you can also set the name on the fly because then you don't need the x:Name most of the time any way. See the following;
private void GoShowUpElement(FrameworkElement element, double opacity)
{
if (element != null)
{
string guidString = Guid.NewGuid().ToString();
element.SetValue(NameProperty, guidString);// When you don't use x:Name in Xaml (with MVVM normally not nessasary)
if (!this.LayoutRoot.Resources.Contains(guidString))
{
this.LayoutRoot.Resources.Add(guidString, ShowUpElement(opacity, 1000, guidString)); // when you do use x:Name replace guidString with the x:Name you used.
Storyboard simultaniousStoryboard = this.LayoutRoot.Resources[guidString] as Storyboard;
simultaniousStoryboard.Completed += new EventHandler(simultaniousStoryboard_Completed);
simultaniousStoryboard.Begin();
}
}
}
When the storyboard completes, I clean up the resources, which significantly increases performance when using more and more storyboards ;)
private void simultaniousStoryboard_Completed(object sender, EventArgs e)
{
Storyboard storyboard = sender as Storyboard;
foreach (DictionaryEntry dictionaryEntry in this.LayoutRoot.Resources)
{
Storyboard resourceStoryboard = dictionaryEntry.Value as Storyboard;
if (resourceStoryboard != null)
{
if (resourceStoryboard.GetValue(NameProperty) == storyboard.GetValue(NameProperty))
this.LayoutRoot.Resources.Remove(dictionaryEntry.Key);
}
}
}
Here is the static Method that creates a reusable storyboard for me.
public static Storyboard ShowUpElement(double opacity, int milliseconds, string elementName)
{
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(StoryboardBasic.KeyFramedAnimation(opacity, 0.9, 0, milliseconds, elementName, "Opacity"));
//storyboard.Children.Add(StoryboardBasic.KeyFramedAnimation.... Add more if you want
return storyboard;
}
And the DoubleAnimationUsingKeyFrames which could also be other types of animations as you like.
public static DoubleAnimationUsingKeyFrames KeyFramedAnimation(double fromValue, double toValue, int startMilliSeconds, int endMilliseconds, string targetElementName, PropertyPath propertyPath)
{
List<SplineDoubleKeyFrame> splineDoubleKeyFrames = new List<SplineDoubleKeyFrame>()
{
new SplineDoubleKeyFrame() { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(startMilliSeconds)), Value = fromValue, KeySpline = new KeySpline() { ControlPoint1 = new Point(0,0), ControlPoint2= new Point(1,0)} },
new SplineDoubleKeyFrame() { KeyTime = KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(endMilliseconds)), Value = toValue, KeySpline = new KeySpline() { ControlPoint1 = new Point(0,0), ControlPoint2= new Point(0,1)} },
};
DoubleAnimationUsingKeyFrames animation = new DoubleAnimationUsingKeyFrames();
foreach (SplineDoubleKeyFrame linearDoubleKeyFrame in splineDoubleKeyFrames)
animation.KeyFrames.Add(linearDoubleKeyFrame);
Storyboard.SetTargetName(animation, targetElementName);
Storyboard.SetTargetProperty(animation, propertyPath);
return animation;
}
Let me know if this was helpfull, Thanks in advance.

Silverlight 4 WriteableBitmap ScaleTransform Exception but was working in v3

I am getting the following exception for code that used to work in silverlight 3 but has stopped working since upgrading to silverlight 4:
System.AccessViolationException was unhandled
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
var OpenFileDialog = new OpenFileDialog();
OpenFileDialog.Filter = "*.jpg|*.jpg";
if (OpenFileDialog.ShowDialog() == true)
{
var file = OpenFileDialog.Files.ToArray()[0];
ScaleStreamAsBitmap(file.OpenRead(), 200);
}
}
public static WriteableBitmap ScaleStreamAsBitmap(Stream file, int maxEdgeLength)
{
file.Position = 0;
var src = new BitmapImage();
var uiElement = new System.Windows.Controls.Image();
WriteableBitmap b = null;
var t = new ScaleTransform();
src.SetSource(file);
uiElement.Source = src;
//force render
uiElement.Effect = new DropShadowEffect() { ShadowDepth = 0, BlurRadius = 0 }; ;
//calc scale
double scaleX = 1;
double scaleY = 1;
if (src.PixelWidth > maxEdgeLength)
scaleX = ((double)maxEdgeLength) / src.PixelWidth;
if (src.PixelHeight > maxEdgeLength)
scaleY = ((double)maxEdgeLength) / src.PixelHeight;
double scale = Math.Min(scaleX, scaleY);
t.ScaleX = scale;
t.ScaleY = scale;
b = new WriteableBitmap(uiElement, t);
return b;
}
}
}
Thanks
I had the same problem and I succeeded to resolve it!
b=new new WriteableBitmap(0, 0);
b.SetSource(file);
b.Render( new Image() { Source = src, Effect = new DropShadowEffect() { ShadowDepth = 0, BlurRadius = 0 } }, new ScaleTransform() { ScaleX = scaleX , ScaleY = scaleY });
And you can remove :uiElement and file.Position!

Problem adding Viewport2DVisual3D from Code

I'm trying to add a Viewport2DVisual3D to a Viewport3D in code, but the visual isn't showing up. Any help understanding why not would be appreciated. The following is the code for the main window.
Is it sufficient to just add the Viewport2DVisual3D to the children of the Viewport3D in order for it to be rendered?
public partial class Window1 : System.Windows.Window
{
public Window1()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(temp);
}
public void temp(object sender, RoutedEventArgs e)
{
Viewport2DVisual3D test = new Viewport2DVisual3D();
MeshGeometry3D testGeometry = new MeshGeometry3D();
Vector3D CameraLookDirection = Main_Target_CameraOR20.LookDirection;
// Calculate the Positions based on the Camera
Point3DCollection myPoint3DCollection = new Point3DCollection();
myPoint3DCollection.Add(new Point3D(-1, 1, 0));
myPoint3DCollection.Add(new Point3D(-1, -1, 0));
myPoint3DCollection.Add(new Point3D(1, -1, 0));
myPoint3DCollection.Add(new Point3D(1, 1, 0));
testGeometry.Positions = myPoint3DCollection;
PointCollection myPointCollection = new PointCollection();
myPointCollection.Add(new Point(0, 0));
myPointCollection.Add(new Point(0, 1));
myPointCollection.Add(new Point(1, 1));
myPointCollection.Add(new Point(1, 0));
testGeometry.TextureCoordinates = myPointCollection;
Int32Collection triangleIndicesCollection = new Int32Collection();
triangleIndicesCollection.Add(0);
triangleIndicesCollection.Add(1);
triangleIndicesCollection.Add(2);
triangleIndicesCollection.Add(2);
triangleIndicesCollection.Add(3);
triangleIndicesCollection.Add(0);
testGeometry.TriangleIndices = triangleIndicesCollection;
DiffuseMaterial myDiffuseMaterial = new DiffuseMaterial(Brushes.White);
Viewport2DVisual3D.SetIsVisualHostMaterial(myDiffuseMaterial, true);
Transform3DGroup myTransform3DGroup = new Transform3DGroup();
ScaleTransform3D myScaleTransform3D = new ScaleTransform3D();
myScaleTransform3D.ScaleX = 2;
myScaleTransform3D.ScaleY = 2;
myScaleTransform3D.ScaleZ = 2;
TranslateTransform3D myTranslateTransform3D = new TranslateTransform3D();
myTranslateTransform3D.OffsetX = -27;
myTranslateTransform3D.OffsetY = 13;
myTranslateTransform3D.OffsetZ = 6;
RotateTransform3D rotateTransform = new RotateTransform3D()
{
Rotation = new AxisAngleRotation3D
{
Angle = -50,
Axis = new Vector3D(0, 1, 0)
}
};
myTransform3DGroup.Children.Add(myTranslateTransform3D);
myTransform3DGroup.Children.Add(myScaleTransform3D);
myTransform3DGroup.Children.Add(rotateTransform);
test.Transform = myTransform3DGroup;
Button myButton = new Button();
myButton.Content = "Test Button";
test.Material = myDiffuseMaterial;
test.Geometry = testGeometry;
test.Visual = myButton;
ZAM3DViewport3D.Children.Add(test);
}
}
It turns out that the problem was the Offset value. So, it is sufficient to add the child to the Viewport3D to have it render. Cheers

Using a Storyboard animation on a programmatically-added control

I'm trying to fade in a new control to my application's "app" area which is programmatically added after the existing controls are removed. My code looks like this:
void settingsButton_Clicked(object sender, EventArgs e)
{
ContentCanvas.Children.Clear();
// Fade in settings panel
NameScope.SetNameScope(this, new NameScope());
SettingsPane s = new SettingsPane();
s.Name = "settingsPane";
this.RegisterName(s.Name, s);
this.Resources.Add(s.Name, s);
Storyboard sb = new Storyboard();
DoubleAnimation settingsFade = new DoubleAnimation();
settingsFade.From = 0;
settingsFade.To = 1;
settingsFade.Duration = new Duration(TimeSpan.FromSeconds(0.33));
settingsFade.RepeatBehavior = new RepeatBehavior(1);
Storyboard.SetTargetName(settingsFade, s.Name);
Storyboard.SetTargetProperty(settingsFade, new PropertyPath(UserControl.OpacityProperty));
ContentCanvas.Children.Add(s);
sb.Children.Add(settingsFade);
sb.Begin();
}
However, when I run this code, I get the error "No applicable name scope exists to resolve the name 'settingsPane'."
What am I possibly doing wrong? I'm pretty sure I've registered everything properly :(
I wouldn't hassle with the NameScopes etc. and would rather use Storyboard.SetTarget instead.
var b = new Button() { Content = "abcd" };
stack.Children.Add(b);
var fade = new DoubleAnimation()
{
From = 0,
To = 1,
Duration = TimeSpan.FromSeconds(5),
};
Storyboard.SetTarget(fade, b);
Storyboard.SetTargetProperty(fade, new PropertyPath(Button.OpacityProperty));
var sb = new Storyboard();
sb.Children.Add(fade);
sb.Begin();
I solved the problem using this as parameter in the begin method, try:
sb.Begin(this);
Because the name is registered in the window.
I agree, the namescopes are probably the wrong thing to use for this scenario. Much simpler and easier to use SetTarget rather than SetTargetName.
In case it helps anyone else, here's what I used to highlight a particular cell in a table with a highlight that decays to nothing. It's a little like the StackOverflow highlight when you add a new answer.
TableCell cell = table.RowGroups[0].Rows[row].Cells[col];
// The cell contains just one paragraph; it is the first block
Paragraph p = (Paragraph)cell.Blocks.FirstBlock;
// Animate the paragraph: fade the background from Yellow to White,
// once, through a span of 6 seconds.
SolidColorBrush brush = new SolidColorBrush(Colors.Yellow);
p.Background = brush;
ColorAnimation ca1 = new ColorAnimation()
{
From = Colors.Yellow,
To = Colors.White,
Duration = new Duration(TimeSpan.FromSeconds(6.0)),
RepeatBehavior = new RepeatBehavior(1),
AutoReverse = false,
};
brush.BeginAnimation(SolidColorBrush.ColorProperty, ca1);
It is possible odd thing but my solution is to use both methods:
Storyboard.SetTargetName(DA, myObjectName);
Storyboard.SetTarget(DA, myRect);
sb.Begin(this);
In this case there is no error.
Have a look at the code where I have used it.
int n = 0;
bool isWorking;
Storyboard sb;
string myObjectName;
UIElement myElement;
int idx = 0;
void timer_Tick(object sender, EventArgs e)
{
if (isWorking == false)
{
isWorking = true;
try
{
myElement = stackObj.Children[idx];
var possibleIDX = idx + 1;
if (possibleIDX == stackObj.Children.Count)
idx = 0;
else
idx++;
var myRect = (Rectangle)myElement;
// Debug.WriteLine("TICK: " + myRect.Name);
var dur = TimeSpan.FromMilliseconds(2000);
var f = CreateVisibility(dur, myElement, false);
sb.Children.Add(f);
Duration d = TimeSpan.FromSeconds(2);
DoubleAnimation DA = new DoubleAnimation() { From = 1, To = 0, Duration = d };
sb.Children.Add(DA);
myObjectName = myRect.Name;
Storyboard.SetTargetName(DA, myObjectName);
Storyboard.SetTarget(DA, myRect);
Storyboard.SetTargetProperty(DA, new PropertyPath("Opacity"));
sb.Begin(this);
n++;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message + " " + DateTime.Now.TimeOfDay);
}
isWorking = false;
}
}

Resources