DataTrigger in code
I've tried to get this working, based on the answer I received to [Convert some XAML to C# using WPF][1], but I'm missing something.
I've pasted a sample of my code below.
// uGrid = UniformGrid
uGrid.Columns=2;
// test - setup first ellipse
Ellipse ellipse1 = new Ellipse() { Width=25, Height=25, Fill=Brushes.DodgerBlue, Margin= new Thickness(3), Opacity=0 };
uGrid.C开发者_如何学Gohildren.Add(ellipse1);
var fadeEllipse1 = new DoubleAnimation() { From = 0, To = 1, Duration = TimeSpan.FromSeconds(this.secondsToFade), FillBehavior=FillBehavior.Stop };
Storyboard.SetTarget(fadeEllipse1, ellipse1);
Storyboard.SetTargetProperty(fadeEllipse1, new PropertyPath(Ellipse.OpacityProperty));
Storyboard storyBoard = new Storyboard();
storyBoard.Children.Add(fadeEllipse1);
storyBoard.RepeatBehavior=RepeatBehavior.Forever;
// test - setup 2nd ellipse using example below
Ellipse ellipse2 = new Ellipse() { Width=25, Height=25, Fill=Brushes.DodgerBlue, Margin= new Thickness(3), Opacity=0 };
uGrid.Children.Add(ellipse2);
var style = new Style(typeof(Ellipse));
var trigger = new DataTrigger();
trigger.Binding = new Binding("Opacity") { ElementName = "ellipse1" };
trigger.Value = 1;
Storyboard sb = new Storyboard();
var fadeEllipse2 = new DoubleAnimation() { From = 0, To = 1, Duration = TimeSpan.FromSeconds(this.secondsToFade), FillBehavior=FillBehavior.Stop };
Storyboard.SetTarget(fadeEllipse2, ellipse2);
Storyboard.SetTargetProperty(fadeEllipse2, new PropertyPath(Ellipse.OpacityProperty));
Storyboard.SetTargetName(fadeEllipse2, ellipse2.Name);
sb.Children.Add(fadeEllipse2);
sb.RepeatBehavior=RepeatBehavior.Forever;
trigger.EnterActions.Add(new BeginStoryboard() { Storyboard = sb });
style.Triggers.Add(trigger);
storyBoard.Begin();
There are several mistakes in your code:
You're creating a style, but you don't use it anywhere, you're missing the line
ellipse2.Style = style;
You're trying to bind to an element with the name
ellipse1
, but it does not exist (having variable with that name is not the same thing). But even if you set theName
ofellipse1
, it wouldn't work. You have to declare the name in XAML for that. In code-behind, you can useSource
and bind to the other ellipse directly, without using names (which would be a better solution anyway, even if using names worked):trigger.Binding = new Binding("Opacity") { Source = ellipse1 };
You're comparing whether two doubles have exactly the same value. That's almost always a bad idea, and in this case especially. The
Opacity
ofellispse1
doesn't change continuously, it changes by jumping. By default, the value changes at most 60 times per second (at least it was that way when I tested it, I didn't find this value documented anywhere). So, theOpacity
might start at exactly 0, stay that way for 1/60 s and then jump to 1/60. Because of this, comparing for exact value is even less reliable than when comparing doubles for equality normally (which is not reliable to start with). Using a converter that checks, whether the opacity is greater than0.99
seems to work for me, but it's still not reliable: if the dispatcher is busy, the opacity can jump, say, from 0.85 straight to 0.12.public class GreaterThanConverter : IValueConverter { public object Convert( dynamic value, Type targetType, dynamic parameter, CultureInfo culture) { return value > parameter; } public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture) { throw new NotSupportedException(); } }
trigger.Binding = new Binding("Opacity") { Source = ellipse1, Converter = new GreaterThanConverter(), ConverterParameter = 0.99 }; trigger.Value = true;
Apparently
A Storyboard tree in a Style cannot specify a TargetName. Remove TargetName.
So delete the following like, it's not useful anyway.
Storyboard.SetTargetName(fadeEllipse2, ellipse2.Name);
精彩评论