2010-01-19 8 views
5

Tengo una vista y un ViewModel en Silverlight 3.0.Enlace bidireccional de la propiedad VerticalOffset en ScrollViewer?

La vista contiene un ScrollViewer estándar, que contiene contenido dinámico.

Dependiendo del contenido dentro del ScrollViewer, el usuario podría haber desplazado la mitad del contenido, y luego realizó una acción que hace que el ScrollViewer cargue contenido nuevo, pero el ScrollViewer no se desplaza automáticamente a la parte superior.

Quiero enlazarme a la propiedad VerticalOffset, pero es de solo lectura. ¿Alguna idea sobre comportamiento conectable? Alguna idea?

Gracias.

+0

desea exponer una propiedad en el modelo de vista que indica que el ScrollViewer debería ser? ¿No está claro a qué quieres vincular VerticalOffset? – AnthonyWJones

Respuesta

3

Dado que está utilizando un ViewModel considero que la "acción que hace que ScrollViewer cargue contenido nuevo" es el resultado de cambios realizados dentro o en ViewModel. Siendo ese el caso, agregaría un evento al ViewModel que se activará cada vez que se produzca dicho cambio.

Su vista puede agregar un controlador en este evento y llamar a ScrollToVerticalPosition en el ScrollViewer cuando se dispara.

4

La siguiente entrada del blog proporciona un comportamiento adjunto que expone los desplazamientos verticales/horizontales de una ScrollViewer para que pueda unirse a ellos, o un conjunto de ellos en código:

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

Esto permite que el siguiente marcado :

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

Me gustaría ver un artículo (necesito la solución wpf para enlazar scrollviewer), pero el enlace es incorrecto. – Sinatr

+0

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

+0

@Thomas gracias - He actualizado el enlace – ColinE

0

he simplificado la solución de @ COLINE. En lugar de conectarme al evento ScrollBar.ValueChanged, conecto al evento ScrollViewer.ScrollChanged. Por lo tanto, 1. no es necesario encontrar el ScrollBar en el árbol visual y 2. ScrollBar.ValueChanged se llama en algunos estados de transición cuando el contenido del ScrollViewer cambia y no quiero ver estos estados.

fijo mi código para el VerticalOffset, la HorizontalOffset es similar:

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

y utilizarlo en el XAML:

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