WPF滑块ValueChanged事件的频率
本文关键字:频率 事件 ValueChanged 滑块 WPF | 更新日期: 2023-09-27 18:29:25
在我的应用程序中,我使用两个滑块来控制某些图像的亮度和对比度,每次当两个滑块中的任何一个更改其值属性时,都必须逐个像素重新计算图像。较小图像的重新计算完全正常,不会造成任何问题,但是,较大图像需要更长的时间来重新计算,并且滑块拇指的移动与鼠标指针相比略有延迟。我确实需要或多或少地实时重新计算图像,所以简单地在DragCompleted
上发生事件或类似情况是不可接受的。
使用滑块的ValueChanged
-事件初始化重新计算。我认为这个问题的一个很好的解决方案是,如果事件没有尽快启动,但至少要等待50毫秒才能再次启动,但有滑块的特性可以控制吗?
我想到的另一个解决方案是,在事件处理开始时从滑块中删除事件,并在短时间后再次添加,但这可能会导致一些延迟,这在这里也是不可取的。
我在任何地方都找不到关于这个话题的任何东西,所以如果有人能给我任何好的建议或指导,我会非常高兴。
您还可以使用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;
}
这样,您只需要降低图像计算的频率,而不会在第一次值更改时出现显著延迟。