2014-02-12 2 views
0

Я работаю над проектом Windows Store 8.1 App и хотел бы создать пользовательский контроль над уровнем производительности/манометром. Класс внутренне измеряет некоторые значения и отображает их как текст и как progressbar/gauge. Значение изменяется должно быть оживленно:Как получить промежуточные значения/шаги анимации DependencyProperty?

public class CustomGauge : UserControl{ 

    private static readonly DependencyProperty SpeedProperty = DependencyProperty.Register("Speed", typeof(double), typeof(CustomGauge), new PropertyMetadata(null, new PropertyChangedCallback(SpeedChanged))); 
    private double Speed{ 
     get { return (double)GetValue(SpeedProperty); } 
     set { SetValue(SpeedProperty , value); } 
    } 

    // In CustomGauge.xaml a TextBlock uses a Binding to Speed to display the value 


    private static void SpeedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { 
     CustomGauge gauge = d as CustomGauge; 
     if (gauge != null) 
      gauge.DrawSpeed(); 
    } 

    private void OnSpeedChanged(double newSpeedValue) { 
     DoubleAnimation animation = new DoubleAnimation(); 
     animation.EnableDependentAnimation = true; 
     animation.Duration = new Duration(TimeSpan.FromSeconds(1.5)); 
     animation.To = newSpeedValue; 

     PowerEase easing = new PowerEase(); 
     easing.Power = 5.0; 
     easing.EasingMode = EasingMode.EaseOut; 

     animation.EasingFunction = easing; 

     Storyboard storyboard = new Storyboard(); 
     storyboard.Children.Add(animation); 
     Storyboard.SetTarget(animation, this); 
     Storyboard.SetTargetProperty(animation, "Speed"); 

     storyboard.Begin(); 
    } 

    private void DrawSpeed() { 
     ... 
    } 
} 

Хотя текст XAML TextBlock, который использует привязку к «Speed» анимированный калибровочному/ProgressBar просто переходит от старого значения к новому без анимации. Это связано с тем, что SpeedChanged (...) вызывается только один раз с новым значением, а не для каждого промежуточного значения анимации от старого к новому значению.

Как я могу решить эту проблему и использовать анимацию, чтобы изменить индикатор/прогрессбар?

ответ

0

Одна вещь, которую вы можете сделать, это создать «Шаг Размер» и «Шаг времени» для вашей анимации. Он будет принимать значение, найти разницу и сократить эту разницу на куски, оживляя каждого.

Примечание: Я использую WinRTXamlToolkit за их замечательный StoryBoard Extensions. Это, возможно, не нужно, и если вы решили не включать всю библиотеку, легко добавить это расширение.

// Set this to something sensible for your speeds. 
// You may want to have it be calculated on the fly, 
// Such as by doing an even distribution of steps, 
// Possibly with a minimum value for a step to be. Up to you. 
private const double StepSize = 5; 

private const double StepTime = 1.5; 

private async void OnSpeedChanged(double newSpeedValue) { 

    DoubleAnimation animation = new DoubleAnimation(); 
    animation.EnableDependentAnimation = true; 

    PowerEase easing = new PowerEase(); 
    easing.Power = 5.0; 
    easing.EasingMode = EasingMode.EaseOut; 

    animation.EasingFunction = easing; 

    Storyboard storyboard = new Storyboard(); 
    storyboard.Children.Add(animation); 
    Storyboard.SetTarget(animation, this); 
    Storyboard.SetTargetProperty(animation, "Speed"); 

    // You may want to have this be an absolute value and store the sign 
    // in case there is both a positive and negative change in speed 
    var difference = newSpeedValue - Speed; 

    for(double stepValue = Speed + StepSize; i < difference; i += StepSize) 
    { 
     animation.Duration = new Duration(TimeSpan.FromSeconds(StepTime)); 
     animation.To = stepValue; 

     await storyboard.BeginAsync(); 
    } 

    // do the last one 
    animation.Duration = new Duration(TimeSpan.FromSeconds(StepTime)); 
    animation.To = newSpeedValue; 

    await storyboard.BeginAsync(); 
} 

Последнее, что нужно отметить, это то, что я сделал OnSpeedChanged async. Для метода SpeedChanged он просто «установит его и забудет» в том смысле, что он его вызовет и немедленно продолжит. Если ваша скорость изменяется регулярно, вам нужно будет сделать какой-то эффект цепочки, например, отменить последние анимации с помощью CancellationToken. Другой вариант - сохранить очередь запущенных задач анимации и выполнить их последовательно. Это может быть или не быть хорошей идеей по ряду причин.

Надеюсь, что это поможет и счастливое кодирование!

Смежные вопросы