2010-01-19 18 views
5

Ho una vista e un ViewModel in Silverlight 3.0.Binding a due vie della proprietà VerticalOffset su ScrollViewer?

La vista contiene un ScrollViewer standard, che contiene contenuto dinamico.

A seconda del contenuto all'interno di ScrollViewer, l'utente poteva scorrere a metà del contenuto e quindi eseguire un'azione che induce ScrollViewer a caricare nuovo contenuto, ma ScrollViewer non scorre automaticamente verso l'alto.

Desidero essere in grado di collegarsi alla proprietà VerticalOffset, ma è di sola lettura. Qualche idea sul comportamento attaccabile? Qualche idea?

Grazie.

+0

si desidera esporre una proprietà sulla ViewModel che indica dove il ScrollViewer dovrebbe essere? Non è chiaro a cosa vorreste legare VerticalOffset? – AnthonyWJones

risposta

3

Poiché si utilizza un ViewModel, prendo in considerazione che "l'azione che causa la visualizzazione di ScrollViewer per caricare nuovi contenuti" è il risultato di modifiche apportate all'interno o al ViewModel. In questo caso, aggiungerei un evento al ViewModel che viene attivato ogni volta che si verifica un tale cambiamento.

La tua vista può aggiungere un gestore su questo evento e chiamare ScrollToVerticalPosition sul ScrollViewer quando viene attivato.

4

Il seguente post sul blog fornisce un comportamento allegato che espone gli offset verticali/orizzontali di uno ScrollViewer in modo che è possibile associare a loro, o metterli in codice:

http://blog.scottlogic.com/2010/07/21/exposing-and-binding-to-a-silverlight-scrollviewers-scrollbars.html

In questo modo il seguente markup :

<ScrollViewer 
    local:ScrollViewerBinding.VerticalOffset="{Binding YPosition, Mode=TwoWay}" 
    local:ScrollViewerBinding.HorizontalOffset="{Binding XPosition, Mode=TwoWay}"> 
    <!-- Big content goes here! --> 
</ScrollViewer> 
+0

Mi piacerebbe vedere un articolo (ho bisogno di una soluzione wpf per legare scrollviewer), ma il collegamento è sbagliato. – Sinatr

+0

http://blog.scottlogic.com/2010/07/21/exposing-and-binding-to-a-silverlight-scrollviewers-scrollbars.html – Thomas

+0

@Thomas grazie - Ho aggiornato il collegamento – ColinE

0

Ho semplificato la soluzione di @ ColinE. Invece di aggancio all'evento ScrollBar.ValueChanged, collego l'evento ScrollViewer.ScrollChanged. Quindi, 1. non è necessario trovare ScrollBar nell'albero visivo e 2. ScrollBar.ValueChanged viene chiamato in alcuni stati di transizione quando il contenuto di ScrollViewer cambia e non voglio rilevare questi stati.

inserisco il mio codice per il VerticalOffset, il HorizontalOffset è simile:

/// <summary> 
/// VerticalOffset attached property 
/// </summary> 
public static readonly DependencyProperty VerticalOffsetProperty = 
    DependencyProperty.RegisterAttached("VerticalOffset", typeof(double), 
    typeof(ScrollViewerBinding), new FrameworkPropertyMetadata(double.NaN, 
     FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, 
     OnVerticalOffsetPropertyChanged)); 
      OnVerticalOffsetPropertyChanged)); 

/// <summary> 
/// Just a flag that the binding has been applied. 
/// </summary> 
private static readonly DependencyProperty VerticalScrollBindingProperty = 
    DependencyProperty.RegisterAttached("VerticalScrollBinding", typeof(bool?), typeof(ScrollViewerBinding)); 

public static double GetVerticalOffset(DependencyObject depObj) 
{ 
    return (double)depObj.GetValue(VerticalOffsetProperty); 
} 

public static void SetVerticalOffset(DependencyObject depObj, double value) 
{ 
    depObj.SetValue(VerticalOffsetProperty, value); 
} 

private static void OnVerticalOffsetPropertyChanged(DependencyObject d, 
    DependencyPropertyChangedEventArgs e) 
{ 
    ScrollViewer scrollViewer = d as ScrollViewer; 
    if (scrollViewer == null) 
     return; 

    BindVerticalOffset(scrollViewer); 
    scrollViewer.ScrollToVerticalOffset((double)e.NewValue); 
} 

public static void BindVerticalOffset(ScrollViewer scrollViewer) 
{ 
    if (scrollViewer.GetValue(VerticalScrollBindingProperty) != null) 
     return; 

    scrollViewer.SetValue(VerticalScrollBindingProperty, true); 
    scrollViewer.ScrollChanged += (s, se) => 
    { 
     if (se.VerticalChange == 0) 
      return; 
     SetVerticalOffset(scrollViewer, se.VerticalOffset); 
    }; 
} 

e utilizzarlo nel XAML:

<ScrollViewer local:ScrollViewerBinding.VerticalOffset="{Binding ScrollVertical}"> 
    <!-- content ... --> 
</ScrollViewer> 
Problemi correlati