WPF绑定延迟

时间:2019-04-05 12:50:18

标签: c# wpf binding dependency-properties

我正在尝试创建一个ProgressBar,它可以从0动画到某个值。大部分时间一切都很好...

我正在使用Owen Johnson中的代码。进行如下更改:

public static readonly DependencyProperty SmoothValueProperty =
    DependencyProperty.RegisterAttached("SmoothValue", typeof(double), typeof(ProgressBarSmoother), 
        new FrameworkPropertyMetadata(0d,  FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, changing, coerceValueCallback, false, System.Windows.Data.UpdateSourceTrigger.PropertyChanged));


private static object coerceValueCallback(DependencyObject d, object baseValue)
{
    Console.WriteLine($"{ (double)baseValue } coercevalue");
    return baseValue;
}

public static void changing(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ProgressBarSmoother obj = d as ProgressBarSmoother;
    Console.WriteLine($"Contador: {++obj.Count}. Valor novo: { e.NewValue }");
    if ((double)e.NewValue == 0)
    {
        obj.ResetAnimation();

        Console.WriteLine($"Contador: {++obj.Count}");
        obj.Value = 0;
        return;
    }

    obj.Animation = new DoubleAnimation(0d, (double)e.NewValue, TimeSpan.FromMilliseconds((double)e.NewValue));
    obj.Animation.Completed += (sender, arg) =>
    {
        obj.Animation = null;
        obj.Value = 0;
        obj.BeginAnimation(ValueProperty, null, HandoffBehavior.SnapshotAndReplace);

        Console.WriteLine("Animation completed");
    };

    obj.Foreground = new SolidColorBrush(Colors.Red);
    obj.BeginAnimation(ValueProperty, obj.Animation, HandoffBehavior.SnapshotAndReplace);

    Console.WriteLine($"Contador: {++obj.Count}");
}

// Basically the code that changes the progressbar value is this
private void Controller_OnPlayerChangedState(object sender, MultiPlayerController.OnChangeStateEventArgs e)
{
    if (e.NewState == AudioPlayer_State.Playing)
    {
        Duration = AudioPanel.Controller.GetDuration();

        panel.SetCurrentPositionAsync (Duration);
    }
    else if(e.NewState != AudioPlayer_State.Playing && e.NewState != AudioPlayer_State.Paused)
    {
        panel.SetCurrentPositionAsync ((long)0);
        //System.Threading.Thread.Sleep(100);
    }
}

(有很多代码仅供测试,看看有什么令人高兴的地方)

我有一个音频播放器,progressbar是要查看音频的实际位置(不能暂停,只能停止)。停止按钮可以正常工作。问题是当“重复”状态被激活时。 我从dll中收到一个事件Stopped(将值设置为0,动画消失了),过了一会儿(大多数时间少于0ms),正在播放,所以我必须用{持续时间。

有时我的动画没有被调用,我放了一些日志来发现白色。不调用时,progressbar仅发生一次。当工作时,调用两次:一次为0,当我销毁较早的动画时,另一次以新的持续时间(与以前相同)。

仅出于测试目的,我在代码中放入了CoerceValueCallback,它将值更改为新的持续时间,并且像一个超级按钮一样工作。我的想法是更改新值的延迟...基本上,我需要先设置为0,然后再设置为新值。

我可以删除较旧的支票需要与新的支票不同吗?或者我可以立即更新该值?

直到现在的解决方案

我在控件Thread.Sleep上创建了名为ProgressBarSmoother的公用函数

ResetAnimation

并创建了public void ResetAnimation() { this.Dispatcher.Invoke(() => { SmoothValue = 0; }); } 的{​​{1}}

getter/setter

在我的SmoothValue

public double SmoothValue
{
    get => (double)GetValue(SmoothValueProperty);
    set => SetValue(SmoothValueProperty, value);
}

我的改变

SetCurrentPositionAsync

所以..当我设置为0时,我立即调用public void SetCurrentPositionAsync (long position) { if (position == 0) progressBar.ResetAnimation(); CurrentPositionAsync = position; } ,它可以设置属性的值并正确设置字段,而不是调用public static void changing(DependencyObject d, DependencyPropertyChangedEventArgs e) { ProgressBarSmoother obj = d as ProgressBarSmoother; if ((double)e.NewValue == 0) { obj.BeginAnimation(ValueProperty, null, HandoffBehavior.SnapshotAndReplace); return; } obj.Animation = new DoubleAnimation(0d, (double)e.NewValue, TimeSpan.FromMilliseconds((double)e.NewValue)); obj.BeginAnimation(ValueProperty, obj.Animation, HandoffBehavior.SnapshotAndReplace); } 并有一些延迟。

我的ResetAnimation

OnPropertyChanged

工作正常,但我不知道是否可以有其他解决方案。

0 个答案:

没有答案