WPF Slider Frequency ValueChanged-Event

In my application, I use two sliders to control the brightness and contrast of certain images, and the image must be completely recalculated pixel by pixel every time one of the two sliders changes its value-property. Recalculating smaller images is completely fine and does not cause any problems, however large images require more time to recount, and the large slider engine moves with a slight delay compared to the mouse pointer. I need the image to be recounted more or less in real time, so a simple event on DragCompleted or similarly is unacceptable.

ValueChanged initialized using the ValueChanged -event slider. I think a good solution to this problem would be if the event were not fired as quickly as possible, but at least wait, say, 50 ms before it is fired again, but is there a slider property that can control by this?

Another solution that I was thinking about is to remove the event from the slider right at the beginning, when the event is processed and added again some short time later, but this may cause some delay, which is also not preferred here.

I could not find anything on this topic anywhere, so if someone has any good suggestions or directions that I could use, I would be very grateful.

+4
source share
4 answers

If you think your application does not need to perform calculations every time the ValueChanged event fires , you can use the DragCompleted Event in Thumb control to determine after the user has finished dragging and dropping the control.

 <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 be careful that this only works when the user drags the slider. This does not work when the user clicks on the slider.

Refer to this to handle other events such as mouse clicks, etc.

If you want to calculate with some time delay, you can use a timer.

EDIT: At your request, you can do this. In the 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(); } 
+4
source

You can also use the BindingBase.Delay property introduced in WPF 4.5.

Just bind the value of the slider to the setting of the Delay dependency property in the binding. This will only update the values ​​after a certain time (e.g. 500 ms), and this can make your application smoother.

+4
source

While you can use BindingBase.Delay, this causes a delay, even if one change is required. another approach might be to use OneWay bindings in the value of the slider and use an asynchronous command, for example:

XAML Code:

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

Thus, you can reduce the frequency of image calculations without significant delay when you first change the value.

+1
source

I could implement this using Backgroundworker , where image processing will be performed on Backgroundworker asynchronously.

And what I will suggest, you can use Timer here and set its tick time to a convenient value. For each event with a slider, you start the timer if it is not turned on. In the timer event handler, you can check whether the background worker is working, you can undo the previous operation and place a new operation on it. In the bacgroundworkerdone event handler, just stop the timer.

thanks

0
source

Source: https://habr.com/ru/post/1499615/


All Articles