2009-10-28 15 views
12

È possibile modificare la quantità di scorrimento di WPF ScrollViewer? Mi sto semplicemente chiedendo se è possibile cambiare lo scrollviewer in modo che quando si utilizza la rotellina del mouse o le frecce dello scrollviewer, la quantità di scorrimento incrementale possa essere modificata.Wpf ScrollViewer Quantità di scorrimento

risposta

12

La risposta breve è: non c'è modo di farlo senza scrivere un codice di scorrimento personalizzato, ma non lasciare che ti spaventi non è poi così difficile.

ScrollViewer funziona scorrendo utilizzando unità fisiche (ovvero pixel) o impegnandosi con un'implementazione IScrollInfo per utilizzare unità logiche. Questo è controllato dall'impostazione the CanContentScroll property dove un valore di falso significa "scorre il contenuto utilizzando unità fisiche" e un valore di vero significa "scorre il contenuto logicamente".

Quindi, come fa ScrollViewer a scorrere il contenuto logicamente? Comunicando con un'implementazione IScrollInfo. Ecco come si può rilevare esattamente quanto il contenuto del pannello scorre quando qualcuno esegue un'azione logica. Take a look at the documentation for IScrollInfo per ottenere un elenco di tutte le unità logiche di misurazione che possono essere richieste per lo scorrimento, ma poiché hai menzionato la rotella del mouse ti interesserà principalmente i metodi MouseWheelUp/Giù/Sinistra/Destra.

0

È possibile implementare un comportamento sullo scrollviewer. Nel mio caso CanContentScroll non ha funzionato. La soluzione seguente funziona per lo scorrimento con la rotellina del mouse e per il draging della barra di scorrimento.

public class StepSizeBehavior : Behavior<ScrollViewer> 
{ 
    public int StepSize { get; set; } 

    #region Attach & Detach 
    protected override void OnAttached() 
    { 
     CheckHeightModulesStepSize(); 
     AssociatedObject.ScrollChanged += AssociatedObject_ScrollChanged; 
     base.OnAttached(); 
    } 

    protected override void OnDetaching() 
    { 
     AssociatedObject.ScrollChanged -= AssociatedObject_ScrollChanged; 
     base.OnDetaching(); 
    } 
    #endregion 

    [Conditional("DEBUG")] 
    private void CheckHeightModulesStepSize() 
    { 
     var height = AssociatedObject.Height; 
     var remainder = height%StepSize; 
     if (remainder > 0) 
     { 
      throw new ArgumentException($"{nameof(StepSize)} should be set to a value by which the height van be divised without a remainder."); 
     } 
    } 

    private void AssociatedObject_ScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     const double stepSize = 62; 
     var scrollViewer = (ScrollViewer)sender; 
     var steps = Math.Round(scrollViewer.VerticalOffset/stepSize, 0); 
     var scrollPosition = steps * stepSize; 
     if (scrollPosition >= scrollViewer.ScrollableHeight) 
     { 
      scrollViewer.ScrollToBottom(); 
      return; 
     } 
     scrollViewer.ScrollToVerticalOffset(scrollPosition); 
    } 
} 

Si potrebbe usare in questo modo:

<ScrollViewer MaxHeight="248" 
       VerticalScrollBarVisibility="Auto"> 
    <i:Interaction.Behaviors> 
     <behaviors:StepSizeBehavior StepSize="62" /> 
    </i:Interaction.Behaviors> 
0

Ho fatto questo per garantire numeri interi sulla scrollbar1.ValueChanged:

scrollbar1.Value = Math.Round(scrollbar1.Value, 0, MidpointRounding.AwayFromZero) 
Problemi correlati