/// <summary> /// Performs an animated iteration through the wrapped collection's /// elements. /// </summary> /// /// <param name="action"> /// the action to perform for every iteration through the collection. /// </param> /// <param name="duration"> /// the number of milliseconds that the animation should last. /// </param> /// <param name="interpolator"> /// the interpolation function that should be used for the animation. /// </param> public void ForEach(IterationAction action, long duration, Interpolator interpolator) { // Perform an animation that will animate through // all of the indices in the collection. var lastIndex = this.Collection.Count() - 1; var indexAnimation = new ValueAnimation(0, lastIndex, duration, interpolator); // Every time the index animation is iterated, iterate the // "loop" and perform the action for every item up to the // current index. int i = 0; indexAnimation.AnimationIncremented += (_, __) => { while (i <= indexAnimation.CurrentValue) { var element = this.Collection.ElementAt(i); action(element, i); i++; } }; // Add the index animation to the list of animations being // performed. this.AddAnimation(indexAnimation); // Start the animation. indexAnimation.Start(); }
/// <summary> /// Animates the object's property with the specified name to the specified value. /// </summary> /// /// <param name="propertyName"> /// the name of the property to animate. The property must be a public property /// of a primitive numeric type and be both readable and writable. /// </param> /// <param name="value"> /// the value to animate the property to. /// </param> /// <param name="duration"> /// the duration the animation should last in milliseconds. /// </param> /// <param name="interpolator"> /// the interpolation function the animation should use. /// </param> public void AnimatePropertyTo(string propertyName, double value, long duration, Interpolator interpolator) { var property = VerifyPropertyName(propertyName); // Retrieve the current value of the property. var propertyValue = this.GetPropertyValue(property); var startValue = (double)Convert.ChangeType(propertyValue, typeof(double)); // Create an animation animating from the property value to the specified // value. var animation = new ValueAnimation(startValue, value, duration, interpolator); this.AddAnimation(animation); // Set the value of the property on every increment of the animation. animation.AnimationIncremented += (_, __) => { var currentValue = Convert.ChangeType(animation.CurrentValue, property.PropertyType); SetPropertyValue(property, currentValue); if (ObjectPropertyChanged != null) { ObjectPropertyChanged(this); } }; // Start the animation. animation.Start(); }
/// <summary> /// Animates the values of all of the object's primitive properties /// to the values of all of the properties with the same names /// and types in the specified object. /// </summary> /// /// <param name="target"> /// the object who contains similarly named properties as the object /// whose values should be animated to. /// </param> public void AnimateTo(object target) { // If the object is immutable, it cannot be animated. if (IsImmutable()) { throw new InvalidOperationException("An immutable object cannot be animated"); } // The value being animated to needs to be the same type as the wrapped // object. var type = Object.GetType(); var targetType = target.GetType(); if (!type.IsAssignableFrom(targetType)) { throw new ArgumentException("The value being animated to must be the same type as the wrapped object"); } // Only primitive instance properties should be animated. var searchFlags = BindingFlags.Instance; var objectProperties = from property in type.GetProperties(searchFlags) where property.PropertyType.IsPrimitive select property; var lastProperty = objectProperties.Last(); foreach (var property in objectProperties) { var startValue = (double)property.GetValue(Object); var endValue = (double)property.GetValue(target); var propertyAnimation = new ValueAnimation(startValue, endValue, DefaultDuration, DefaultInterpolator); propertyAnimation.AnimationIncremented += (_, __) => property.SetValue(Object, propertyAnimation.CurrentValue); this.AddAnimation(propertyAnimation); // Once the last property is incremented, the ObjectChanged event should be triggered. if (property.Equals(lastProperty)) { propertyAnimation.AnimationIncremented += (_, __) => { if (ObjectChanged != null) { ObjectChanged(this); } } } ; propertyAnimation.Start(); } }
/// <summary> /// Starts the specified animation. /// </summary> /// /// <param name="animation"> /// the animation to be started. /// </param> private void StartAnimation(ValueAnimation animation) { // Ensure the value is not already being animated. if (Animations.Length > 1) { // Remove the animation, since only one animation can run at a time. RemoveAnimation(animation, new AnimationEventArgs(animation)); return; } // Update the value at every animation frame. animation.AnimationIncremented += (_, __) => Value = animation.CurrentValue; // Start the animation. animation.Start(); }