public class LambdaCollection <T>: Collection <T> where T: DependencyObject, new () { public LambdaCollection (int count) {while (count -> 0) Add (new T ()); } â‹® }
DependencyObject
and have a default constructor), and added a constructor that creates a certain number of objects we need. And now the most interesting thing is that we add a method that can initialize the properties of T
objects using lambda delegates:public class LambdaCollection <T>: Collection <T> where T: DependencyObject, new () { â‹® public LambdaCollection <T> WithProperty <U> (DependencyProperty property, Func <int, U> generator) { for (int i = 0; i <Count; ++ i) this [i] .SetValue (property, generator (i)); return this; } }
return this
at the end. He himself takes two parameters. The first parameter is the property that we want to change in all elements of the collection . This seriously simplifies life as it is not necessary to write cycles everywhere. The second parameter is a reference to a value generator — that is, a function that takes an index of an item in the collection and returns a value of type U
And the tim itself can be anything, the main thing is that it fits the property.double
, you cannot generate int
type values, you will get an exception.var circles = new LambdaCollection <Ellipse> (10) .WithProperty (WidthProperty, i => 1.5 * (i + 1)) .WithProperty (HeightProperty, i => 1.5 * (i + 1));
public class LambdaCollection <T>: Collection <T> where T: DependencyObject, new () { â‹® public LambdaCollection <T> WithXY <U> (Func <int, U> xGenerator, Func <int, U> yGenerator) { for (int i = 0; i <Count; ++ i) { this [i] .SetValue (Canvas.LeftProperty, xGenerator (i)); this [i] .SetValue (Canvas. TopProperty, yGenerator (i)); } return this; } }
int count = 20; var circles = new LambdaCollection <Ellipse> (count) .WithXY (i => 100.0 + (4.0 * i * Math.Sin (i / 4.0 * (Math.PI))), i => 100.0 + (4.0 * i * Math.Cos (i / 4.0 * (Math.PI)))) .WithProperty (WidthProperty, i => 1.5 * i) .WithProperty (HeightProperty, i => 1.5 * i) .WithProperty (Shape.FillProperty, i => new SolidColorBrush ( Color.FromArgb (255, 0, 0, (byte) (255 - (byte) (12.5 * i))))); foreach (var circle in circles) MyCanvas.Children.Add (circle);
DoubleAnimation
is boring. It is much more interesting when we ourselves control the value of an element. If we take this type for an example, then it is very easy to redefine it so that the animated value is controlled by our generator:public class LambdaDoubleAnimation: DoubleAnimation { public Func <double, double> ValueGenerator {get; set; } protected override double GetCurrentValueCore (double origin, double dst, AnimationClock clock) { return ValueGenerator (base.GetCurrentValueCore (origin, dst, clock)); } }
public class LambdaDoubleAnimationCollection: Collection <LambdaDoubleAnimation> { â‹® public LambdaDoubleAnimationCollection (int count, Func <int, double> from, Func <int, double> to, Func <int, Duration> duration, Func <int, Func <double, double >> valueGenerator) { for (int i = 0; i <count; ++ i) { var lda = new LambdaDoubleAnimation { From = from (i), To = to (i), Duration = duration (i) ValueGenerator = valueGenerator (i) }; Add (lda); } } public void BeginApplyAnimation (UIElement [] targets, DependencyProperty property) { for (int i = 0; i <Count; ++ i) targets [i] .BeginAnimation (property, Items [i]); } }
valueGenerator
parameter expects a 2nd order function, or a “function generator function,” that is, a generator that depends on the index in the collection and whose value depends on the interpolated double
value during the animation. In C #, this means that a “double lambda” must be passed here, for example, i => j => f(j)
.var c = new LambdaDoubleAnimationCollection ( circles.Count, i => 10.0 * i, i => new Duration (TimeSpan.FromSeconds (2)), i => j => 100.0 / j); c.BeginApplyAnimation (circles.Cast <UIElement> (). ToArray (), Canvas.LeftProperty);
UIElement[]
. And the array is chosen precisely because you want to know the length right away - although you could use IEnumerable
.LambdaDoubleAnimationCollection
:public class LambdaDoubleAnimationCollection: Collection <LambdaDoubleAnimation> { â‹® public void BeginApplyAnimation (UIElement [] targets, DependencyProperty property) { for (int i = 0; i <Count; ++ i) { Items [i] .BeginTime = new TimeSpan (0); targets [i] .BeginAnimation (property, Items [i]); } } public void BeginSequentialAnimation (UIElement [] targets, DependencyProperty property) { TimeSpan acc = new TimeSpan (0); for (int i = 0; i <Items.Count; ++ i) { Items [i] .BeginTime = acc; acc + = Items [i] .Duration.TimeSpan; } for (int i = 0; i <Count; ++ i) { targets [i] .BeginAnimation (property, Items [i]); } } }
Source: https://habr.com/ru/post/57236/
All Articles