2012-12-13 13 views
6

In XAML ho il <Slider />. Ha l'evento ValueChanged. Questo evento si attiva con ogni modifica al valore. Devo rilevare quando il cambio di valore è finito. LostFocus, PointerReleased non è l'evento corretto. Come posso rilevare questo?Come posso rilevare quando il cursore XAML è stato completato?

+0

Forse un timer collegato a ValueChanged? –

+0

Sembra che quello con cui stai lottando stia definendo esattamente quando vuoi ricevere questo evento. Penso che se lo capisci allora probabilmente capirai come inviarlo. Forse uno slider con opzioni di valore discreto renderebbe questo più chiaro? – mydogisbox

+0

Hai mai risolto questo problema? – Carlo

risposta

7

È possibile creare una nuova classe ed ereditare da Slider. Da lì in poi, puoi cercare il Thumb control & per ascoltare gli eventi che desideri.

Qualcosa del genere dovrebbe funzionare:

public class SliderValueChangeCompletedEventArgs : RoutedEventArgs 
{ 
    private readonly double _value; 

    public double Value { get { return _value; } } 

    public SliderValueChangeCompletedEventArgs(double value) 
    { 
     _value = value; 
    } 
} 
public delegate void SlideValueChangeCompletedEventHandler(object sender, SliderValueChangeCompletedEventArgs args); 

public class ExtendedSlider : Slider 
{ 
    public event SlideValueChangeCompletedEventHandler ValueChangeCompleted; 
    private bool _dragging = false; 

    protected void OnValueChangeCompleted(double value) 
    { 
     if (ValueChangeCompleted != null) 
     { 
      ValueChangeCompleted(this, new SliderValueChangeCompletedEventArgs(value)); 
     } 
    } 

    protected override void OnApplyTemplate() 
    { 
     base.OnApplyTemplate(); 
     var thumb = base.GetTemplateChild("HorizontalThumb") as Thumb; 
     if (thumb != null) 
     { 
      thumb.DragStarted += ThumbOnDragStarted; 
      thumb.DragCompleted += ThumbOnDragCompleted; 
     } 
     thumb = base.GetTemplateChild("VerticalThumb") as Thumb; 
     if (thumb != null) 
     { 
      thumb.DragStarted += ThumbOnDragStarted; 
      thumb.DragCompleted += ThumbOnDragCompleted; 
     } 
    } 

    private void ThumbOnDragCompleted(object sender, DragCompletedEventArgs e) 
    { 
     _dragging = false; 
     OnValueChangeCompleted(this.Value); 
    } 

    private void ThumbOnDragStarted(object sender, DragStartedEventArgs e) 
    { 
     _dragging = true; 
    } 

    protected override void OnValueChanged(double oldValue, double newValue) 
    { 
     base.OnValueChanged(oldValue, newValue); 
     if (!_dragging) 
     { 
      OnValueChangeCompleted(newValue); 
     } 
    } 
} 
1

Ho avuto un problema simile utilizzando uno Slider su Windows8/WinRT.

Il mio problema era il seguente: stavo reagendo all'evento ValueChanged ed eseguivo un'operazione di lunga durata (scrivendo in modo asincrono su un file) dopo ogni trigger. E quindi incorrere in un'eccezione di modifica simultanea. Per evitare questo, ho usato uno DispatcherTimer.

//Class member 
    private DispatcherTimer myDispatcherTimer = null; 

    private void OnSliderValueChanged(object sender, RangeBaseValueChangedEventArgs e) 
    { 
     //I update my UI right away 
     ... 

     //If the dispatcher is already created, stop it 
     if (myDispatcherTimer!= null) 
      myDispatcherTimer.Stop(); 

     //Overwrite the DispatcherTimer and thus reset the countdown 
     myDispatcherTimer= new DispatcherTimer(); 
     myDispatcherTimer.Tick += (sender, o) => DoSomethingAsync(); 
     myDispatcherTimer.Interval = new TimeSpan(0,0,2); 
     myDispatcherTimer.Start(); 
    } 

    private async void DoSomethingAsync() 
    { 
     await DoThatLongSaveOperation(); 
    } 

Non è possibile rilevare direttamente ciò che il valore finale è, ma si può almeno ritardare l'operazione fino a quando c'è una lunga pausa tra due aggiornamenti (ad esempio, nel mio caso, se l'utente trascina il cursore e si ferma, pur mantenendo il trascinamento per 2 secondi, l'operazione di salvataggio verrà comunque attivata).

+0

Ack! Un timer 2 secondi? Perché non 1. 1 secondo, perché non 3? Penso che preferirei eventi espliciti. Cosa succede se il loro sistema è lento? Cosa succede se il loro sistema è veloce? Sai cosa intendo. –

1

È possibile utilizzare una coppia di valori boolèValueChanged e (se possibile modificare il valore senza la manipolazione del puntatore ) isPressed;

private void Slider_ValueChanged(object s, RangeBaseValueChangedEventArgs e) { 
    if (!isPressed) { 
     AcceptChanges(); 
    } else { 
     isValueChanged = true; 
    } 
} 

codice di inizializzazione:

Window.Current.CoreWindow.PointerPressed += (e, a) => { isPressed = true; }; 

Window.Current.CoreWindow.PointerReleased += (e, a) => { 
    isPressed = false; 
    if (isValueChanged) AcceptChanges(); 
}; 
+0

Non sicuro che questo supporterà la tastiera. –

8

XAML, WinRT, Windows8.1 e UWP:

PointerCaptureLost evento dovrebbe funzionare per il mouse/tocco
KeyUp evento per tastiera

Problemi correlati