WPF滑块的频率ValueChanged-Event

时间:2013-08-29 12:26:44

标签: c# wpf events slider

在我的应用程序中,我使用两个滑块来控制某些图像的亮度和对比度,当两个滑块中的任何一个更改其value-property时,每次都必须逐个像素地重新计算图像。 重新计算较小的图像完全没有问题,并且不会引起任何问题,但是,较大的图像需要更长的时间来重新计算,并且滑块拇指与鼠标指针相比稍微延迟移动。我确实需要实时或多或少地重新计算图像,因此只需在DragCompleted或类似情况下进行事件就不可接受。

使用滑块的ValueChanged - 事件初始化重新计算。 我认为这个问题的一个很好的解决方案是,如果事件没有尽快被触发,但至少会在再次触发之前等待50ms,但是是否有滑块的属性可以控制它?

我想到的另一个解决方案是在处理事件时从开始时从滑块中删除事件,并在稍后的某个时间再次添加它,但这可能会导致一些延迟本身,这也不是首选。 / p>

我无法在任何地方找到关于这个主题的任何内容,所以如果有人有任何好的建议或指示我会用,我会非常感激。

4 个答案:

答案 0 :(得分:4)

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

<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());
}

但请注意,只有当用户拖动滑块时才会起作用。当用户点击滑块时,这不会被触发。

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

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

修改 根据您的要求,您可以这样做。 在'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();
  }

答案 1 :(得分:4)

您还可以使用WPF 4.5中引入的BindingBase.Delay property

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

答案 2 :(得分:0)

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

我还建议你在这里使用Timer并将其滴答时间设置为舒适值。在每个sliderchanged事件中,如果未启用计时器,则启动计时器。在计时器刻度事件处理程序中,您可以检查后台工作程序是否正在工作,然后您可以取消上一个操作并对其执行新操作。在bacgroundworkerdone事件处理程序中,只需停止计时器。

由于

答案 3 :(得分:0)

虽然您可以使用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;

    }

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