WPF滑块ValueChanged事件的频率

本文关键字:频率 事件 ValueChanged 滑块 WPF | 更新日期: 2023-09-27 18:29:25

在我的应用程序中,我使用两个滑块来控制某些图像的亮度和对比度,每次当两个滑块中的任何一个更改其值属性时,都必须逐个像素重新计算图像。较小图像的重新计算完全正常,不会造成任何问题,但是,较大图像需要更长的时间来重新计算,并且滑块拇指的移动与鼠标指针相比略有延迟。我确实需要或多或少地实时重新计算图像,所以简单地在DragCompleted上发生事件或类似情况是不可接受的。

使用滑块的ValueChanged-事件初始化重新计算。我认为这个问题的一个很好的解决方案是,如果事件没有尽快启动,但至少要等待50毫秒才能再次启动,但有滑块的特性可以控制吗?

我想到的另一个解决方案是,在事件处理开始时从滑块中删除事件,并在短时间后再次添加,但这可能会导致一些延迟,这在这里也是不可取的。

我在任何地方都找不到关于这个话题的任何东西,所以如果有人能给我任何好的建议或指导,我会非常高兴。

WPF滑块ValueChanged事件的频率

您还可以使用WPF 4.5中引入的BindingBase.Delay属性。

只需将Slider的值绑定到绑定上的依赖属性设置Delay即可。这将导致只有在特定时间(例如500毫秒)后才更新价值,这可以使您的应用程序更流畅。

如果您认为应用程序不需要在每次触发ValueChanged事件时进行计算,则可以使用Thumb控件中的DragCompletedevent来确定用户完成拖动控件后的位置。

<Slider Thumb.DragCompleted="Slider_DragCompleted_1"  
    Height="27" Margin="132,162,0,0" VerticalAlignment="Top" Width="303"/>

当用户停止拖动时,

private void Slider_DragCompleted_1(object sender, DragCompletedEventArgs e)
{
    Slider s = sender as Slider;
    // Your code
    MessageBox.Show(s.Value.ToString());
}

但要注意,这只适用于用户拖动滑块的情况。当用户单击滑块时,不会触发此操作。

请参阅此以处理其他事件,如鼠标点击等。

如果你想计算一些时间延迟,那么你可以使用计时器。

编辑:根据你的要求,你可以这样做。在"ValueChanged"事件中。

 // Start a new thread only if the thread is stopped 
 // or the thread has not been created yet.
 if (threadPopular == null || threadPopular.ThreadState == ThreadState.Stopped)
 {
           threadPopular = new Thread(new ThreadStart(Your function));
           threadPopular.Start();
  }

我可以使用Backgroundworker来实现这一点,其中图像处理将在Backgroundworker上异步完成。

此外,我建议您可以在这里使用Timer,并将其计时时间设置为舒适值。在每次滑动更改事件中,如果计时器未启用,则启动计时器。在timer-tick事件处理程序中,您可以检查后台工作人员是否正在工作,然后可以取消上一个操作并将新操作放在上面。在bacgroundworker事件处理程序内,只需停止计时器。

感谢

虽然可以使用BindingBase.Delay,但即使需要进行一次更改,也会导致延迟。另一种方法可能是在Slider Value中使用OneWay绑定,并使用异步命令,如下所示:

XAML代码:

<Slider Value="{Binding MyValue, Mode=OneWay}">
    <i:Interaction.Triggers>
     <i:EventTrigger EventName="ValueChanged">
        <mvvmlight:EventToCommand 
        Command="{Binding SetValueCommand, Mode=OneWay}"
        EventArgsConverter="{StaticResource 
        RoutedPropertyChangedEventArgsToDoubleConverter}"
        PassEventArgsToCommand="True" />
        </i:EventTrigger>
     </i:Interaction.Triggers>

值转换器:

using GalaSoft.MvvmLight.Command;
    public class RoutedPropertyChangedEventArgsToDoubleConverter : IEventArgsConverter
    {
        public object Convert(object value, object parameter)
        {
            var args = (RoutedPropertyChangedEventArgs<double>)value;
            var element = (FrameworkElement)parameter;
            return args.NewValue;
        }
    }

命令的回调:

    double _updateVal;
    Task _delay;
    private async void SetValue(double val)
    {            
        if (_delay != null)
        {
            // in case of high frequency updates, most updates will return here
            _updateVal = val; 
            return;
        }
        // only the first update reaches here
        // caluclate the image here 
        MyValue = val; // update slider
        _delay = Task.Delay(500);
        await _delay;
        // in case there are pending updates:
        while (_updateVal.HasValue)
        {
            // caluclate the image here 
            MyValue = _updateVal.Value; // update slider
            _updateVal = null;
            _delay = Task.Delay(500);
            await _delay;
        }
        _delay = null;
    }

这样,您只需要降低图像计算的频率,而不会在第一次值更改时出现显著延迟。