滑块绑定会导致性能显着下降

时间:2018-04-27 17:08:56

标签: c# .net wpf xaml controls

正如标题所说,我有一个自定义滑块,声明如下:

<customControls:ThumbDragSlider IsEnabled="{Binding PlayerSourceState}"
                                Style="{StaticResource {x:Type Slider}}"
                                Value="{Binding CurrentMediaPlayer.MediaElement.Position, Mode=TwoWay, Converter={converters:SecondsToTimeSpanConverter}}"/>

还有更多属性被设置,更多事件和一些命令绑定,但我已经省略了它们,因为我已经将性能问题缩小到这个特定的行:

Value="{Binding CurrentMediaPlayer.MediaElement.Position, Mode=TwoWay, Converter={converters:SecondsToTimeSpanConverter}}"

删除它也会消除所有延迟。在我的电脑上它运行得很好,但是在没有GPU的旧机器上进行测试时,仅使用CPU,它运行不好。此滑块用于浏览MediaElement,滞后在实际媒体文件中最为普遍,甚至是快门。

转换器声明如下:

[ValueConversion(typeof(double), typeof(TimeSpan))]
public class SecondsToTimeSpanConverter : BaseConverter, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if (value is TimeSpan ts)
        {
            return ts;
        }
        return TimeSpan.FromSeconds((double)value);
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        return TimeSpan.FromSeconds((double)value);
    }
}

自定义滑块如下:

public class ThumbDragSlider : Slider
{
    public event DragStartedEventHandler DragStarted;
    public event DragCompletedEventHandler DragCompleted;
    public event EventHandler<MouseEventArgs> ThumbMouseEnter;

    public new TimeSpan Value
    {
        get => TimeSpan.FromSeconds(base.Value);
        set => base.Value = value.TotalSeconds;
    }

    public ThumbDragSlider()
    {
        Loaded += OnLoaded;
    }

    private void OnLoaded(object sender, System.Windows.RoutedEventArgs e)
    {
        Loaded -= OnLoaded;
        var track = this.GetElementFromTemplate<Track>("PART_Track");
        track.Thumb.MouseEnter += (o, args) => ThumbMouseEnter?.Invoke(o, args);
    }

    protected override void OnThumbDragStarted(DragStartedEventArgs e)
    {
        base.OnThumbDragStarted(e);
        DragStarted?.Invoke(this, e);
    }

    protected override void OnThumbDragCompleted(DragCompletedEventArgs e)
    {
        base.OnThumbDragCompleted(e);
        DragCompleted?.Invoke(this, e);
    }
}

每隔250ms会触发一个计时器事件,以使滑块值与MediaElement值同步,绑定无法执行此操作,因为MediaElement没有DependencyProperty负责对于Position,也没有正在被解雇的INotifyPropertyChanged事件。

System.Timers.Timer的事件处理程序:

Application.Current.Dispatcher.Invoke(() => sMovieSkipSlider.Value =
    ViewModel.CurrentMediaPlayer.MediaElement.Position);

可能导致问题的原因是什么?如何解决?

3 个答案:

答案 0 :(得分:1)

我真的不需要创建自定义滑块。我相信这可以通过使用常规滑块来实现。

您说明了以下内容:

  

每隔250ms会触发一个计时器事件,以使滑块值与MediaElement值同步,绑定无法执行此操作,因为MediaElement没有DependencyProperty负责对于Position,也没有正在被解雇的INotifyPropertyChanged事件。

然后没有必要使用绑定,您可以简单地处理滑块的MouseLeftButtonUpEvent并以此方式设置Position的{​​{1}}。
也许每250ms更新一次的计时器也可能太快,当然这取决于您的要求。就像你计划高精度地使用它一样。但是如果你只想要一个简单的玩家,那么每1秒更新一次就足够了。

以下是初始化更新滑块的计时器的示例:

MediaElement

private TimeSpan TotalTime; private DispatcherTimer MediaTimer; private void CurrentMediaPlayer_MediaOpened(object sender, RoutedEventArgs e) { TotalTime = CurrentMediaPlayer.MediaElement.NaturalDuration.TimeSpan; MediaTimer = new DispatcherTimer(); MediaTimer.Interval = TimeSpan.FromSeconds(1); //If 1 second is too slow, change this to: TimeSpan.FromMilliseconds(250) MediaTimer.Tick += new EventHandler(MediaTimer_Tick); MediaTimer.Start(); } private void MediaTimer_Tick(object sender, EventArgs e) { if (CurrentMediaPlayer.MediaElement.NaturalDuration.TimeSpan.TotalSeconds > 0) { if (TotalTime.TotalSeconds > 0) { sMovieSkipSlider.Value = CurrentMediaPlayer.MediaElement.Position.TotalSeconds / TotalTime.TotalSeconds; } } } 添加到滑块:

MouseLeftButtonUpEventHandler

以下是处理事件以更新sMovieSkipSlider.AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler(sMovieSkipSlider_MouseLeftButtonUp), true); 的{​​{1}}的示例:

Position

评论:我已经搞砸了你的一些MVVM设置,但这至少应该让你朝着正确的方向前进。您可以随时使用视图的MediaElement属性。

答案 1 :(得分:1)

您是否尝试过设置绑定延迟?

NET_SALES
0   818817.2
1   362377.2
2   374644.6
3   518613.0
4   368510.9
5   374644.6
6   NaN
7   46382.5
8   55933.7
9   292303.4
10  382928.6

也许你必须玩不同的价值观。

答案 2 :(得分:0)

没有设置值会导致绑定触发并更新媒体播放器的位置,但是由于经过几毫秒才发生这一切,媒体播放器会稍微跳回来引起口吃?我会采取措施在同步过程中不更新媒体播放器的位置。