WPF-slider ValueChanged-Event 的频率
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18510994/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Frequency of WPF-slider ValueChanged-Event
提问by philkark
In my application I use two sliders to control the brightness and contrast of certain images and the image has to be completely recalculated pixel by pixel every single time when either one of the two sliders changes its value-property.
The recalculation of smaller images goes completely fine and doesn't cause any problems, however, larger images need longer to be recalculated and the slider thumb moves with a slight delay compared to the mouse pointer. I do need the image to be recalculated more or less in real time so simply having an event on DragCompletedor similarly is not acceptable.
在我的应用程序中,我使用两个滑块来控制某些图像的亮度和对比度,并且当两个滑块中的任何一个更改其 value-property 时,每次都必须逐个像素地完全重新计算图像。重新计算较小的图像完全没问题,不会引起任何问题,但是,较大的图像需要更长的时间重新计算,并且与鼠标指针相比,滑块的移动略有延迟。我确实需要或多或少地实时重新计算图像,因此简单地进行DragCompleted或类似的事件是不可接受的。
The recalculation is initialized using the ValueChanged-event of the slider.
I think a good solution to this problem would be if the event is not fired as quickly as possible but will at least wait say 50ms before it is fired again, but is there a property of a slider that can control that?
使用ValueChanged滑块的-event初始化重新计算。我认为这个问题的一个很好的解决方案是,如果事件没有尽快触发,但至少会等待 50 毫秒后再次触发,但是是否有滑块的属性可以控制它?
Another solution I was thinking of, is removing the event from the slider right at the start when the event gets handled and adding it again some short time later, but that might cause some delay itself which is also not preferred here.
我正在考虑的另一个解决方案是,在处理事件时从一开始就从滑块中删除事件,并在短时间内再次添加它,但这本身可能会导致一些延迟,这在这里也不受欢迎。
I couldn't really find anything on this topic anywhere, so if somebody has any good suggestions or directions I could use, I would be very greatful.
我在任何地方都找不到关于这个主题的任何内容,所以如果有人有任何我可以使用的好的建议或方向,我会非常感激。
采纳答案by Naren
If you think your application don't need to do the calculations every time the ValueChangedevent is triggered,You can use the DragCompletedEvent in Thumb control to determine the position after the user finished dragging the control.
如果您认为您的应用程序不需要在每次触发ValueChanged事件时都进行计算 ,您可以使用Thumb 控件中的DragCompleted事件来确定用户完成拖动控件后的位置。
<Slider Thumb.DragCompleted="Slider_DragCompleted_1"
Height="27" Margin="132,162,0,0" VerticalAlignment="Top" Width="303"/>
When the user stopped dragging,
当用户停止拖动时,
private void Slider_DragCompleted_1(object sender, DragCompletedEventArgs e)
{
Slider s = sender as Slider;
// Your code
MessageBox.Show(s.Value.ToString());
}
But beware that this works only when user drags the slider.This doesn't get triggered when user clicks on the slider.
但请注意,这仅在用户拖动滑块时有效。当用户单击滑块时不会触发此操作。
Refer thisfor handling other events like mouse click etc..
请参阅此以处理其他事件,例如鼠标单击等。
If you want to calculate with some time delay then you can use a timer .
如果您想计算一些时间延迟,那么您可以使用计时器。
EDIT:Based on your request you can do like this. In the 'ValueChanged' event.
编辑:根据您的要求,您可以这样做。在“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();
}
回答by Libor
You can also make use of BindingBase.Delay propertyintroduced in WPF 4.5.
您还可以使用WPF 4.5 中引入的BindingBase.Delay 属性。
Simply bind Slider's value to a dependency property setting Delayon the binding. This will cause value updates only after certain time (e.g. 500 ms) and this can make your app smoother.
只需将 Slider 的值绑定到绑定上的依赖属性设置Delay。这只会在特定时间(例如 500 毫秒)后导致值更新,这可以使您的应用程序更流畅。
回答by Nitin
I might implement this using the Backgroundworkerwhere image processing will be done on Backgroundworkerasynchronously.
我可能会使用Backgroundworker将Backgroundworker异步完成图像处理的位置来实现这一点。
Also what I will suggest is you can use Timerhere and set its tick time to the comfortable value. On every sliderchanged event, you start the timer if it is not enabled. In timer tick event handler you can check if the background worker is working then you can cancel the previous operation and put the new operation on it. In bacgroundworkerdone event handler, just stop the timer.
另外我建议你可以Timer在这里使用并将其滴答时间设置为舒适的值。在每个sliderchanged 事件上,如果未启用,则启动计时器。在计时器滴答事件处理程序中,您可以检查后台工作人员是否正在工作,然后您可以取消之前的操作并将新操作放在上面。在 bacgroundworkerdone 事件处理程序中,只需停止计时器即可。
Thanks
谢谢
回答by Nina Kaprez
While you could use BindingBase.Delay, this causes a delay even when a single change is required. another approach might be to use a OneWaybinding in the Slider Value and use an asynchronous command like so:
虽然您可以使用 BindingBase.Delay,但即使需要进行单个更改,这也会导致延迟。另一种方法可能是在 Slider Value 中使用OneWay绑定并使用像这样的异步命令:
XAML code:
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>
Value Converter:
价值转换器:
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;
}
}
And the callback for the command:
以及命令的回调:
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;
}
This way you only get to reduce the frequency of the image calculations without a significant delay on the first value change.
通过这种方式,您只能降低图像计算的频率,而不会在第一次值更改时出现明显延迟。

