2013-08-29 71 views
4

在我的應用程序使用兩個滑塊控制亮度和某些圖像的對比度和圖像必須完全重新計算逐個像素每一次當兩個滑塊中的任一個改變其價值屬性。 較小的圖像的重新計算進入完全細,並且不會引起任何問題,然而,較大的圖像需要更長的時間來重新計算並具有稍微延遲的滑塊移動相比鼠標指針。我確實需要實時重新計算圖像,因此只需在DragCompleted或類似情況下發生事件是不可接受的。頻率WPF的滑塊的ValueChanged-事件

重新計算是使用ValueChanged -event滑塊的初始化。 我覺得很好的解決了這個問題是,如果事件不盡快解僱,但至少會等待50ms的說,它再次被解僱之前,但有一個滑塊可以控制的財產?

我想到的另一個解決方案是在事件得到處理時從滑塊右側移除事件並在短時間後再次添加它,但這可能會導致一些延遲本身,這在此也不是優選的。

我真的無法找到關於這個話題的任何地方任何東西,所以如果有人有我可以使用什麼好的建議或指示,我會非常感激。

回答

4

如果你認爲你的應用程序不需要每次觸發的ValueChanged事件的時間做計算,你可以使用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()); 
} 

但要注意的是,當用戶拖動slider.This不會被觸發這隻有當滑塊用戶點擊。

參考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(); 
    } 
+0

謝謝你的回答,但正如我在我的問題中提到的,圖像必須在滑塊移動時實時重新計算。 – phil13131

+1

@ phil13131所以你想減少移動滑塊的滯後? – Naren

+0

嗯,是的,這是我在我的問題中指定的。 – phil13131

0

我可能會使用Backgroundworker其中圖像處理將在Backgroundworker進行異步實現這一點。

此外,我會建議您可以在這裏使用Timer並將其tick時間設置爲舒適的值。在每個sliderchanged事件上,如果未啓用定時器,則啓動該定時器。在計時器滴答事件處理程序中,您可以檢查後臺工作人員是否正在工作,然後您可以取消先前的操作並將新的操作放在上面。在bacgroundworkerdone事件處理程序中,只需停止計時器。

感謝

+0

感謝您的迴應,儘管我覺得每次在'ValueChanged'上啓動一個計時器都不是一個好的解決方案,因爲當用戶滑動時,事件被頻繁地觸發,因此您基本上可以啓動計時器,有點太頻繁。 另外我不知道是否需要定時器,如果我想看看Backgroundworker是否仍在工作.. – phil13131

+0

定時器只是提供時間間隔,直到下一個處理完成。例如,如果我想要,我將以250毫秒的間隔處理圖像,只有當我獲得連續事件時。只有當它停止時,我們纔會啓動計時器。 – Nitin

4

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

只需在綁定上將Slider的值綁定到依賴屬性設置Delay即可。這隻會在一定時間後(例如500毫秒)纔會更新值,這可以讓您的應用更流暢。

1

儘管可以使用BindingBase.Delay,但即使需要單個更改,也會導致延遲。另一種方法可能是使用一個單向在滑塊值結合和使用異步命令像這樣:

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; 

    } 

這樣,您只需減少圖像計算的頻率,而不會在第一次更改值時出現明顯延遲。