2010-01-19 8 views
5

Ich habe eine Ansicht und ein ViewModel in Silverlight 3.0.Zwei-Wege-Bindung der VerticalOffset-Eigenschaft auf ScrollViewer?

Die Ansicht enthält einen Standard-ScrollViewer, der dynamischen Inhalt enthält.

Je nach dem Inhalt des ScrollViewers kann der Benutzer den Inhalt halb durchgeblättert haben und dann eine Aktion ausgeführt haben, die den ScrollViewer zum Laden neuer Inhalte veranlasst, aber der ScrollViewer blättert nicht automatisch nach oben.

Ich möchte in der Lage sein, an die VerticalOffset-Eigenschaft zu binden, aber es ist schreibgeschützt. Irgendwelche Ideen zum ansteckbaren Verhalten? Irgendwelche Ideen?

Danke.

+0

Sie mögen eine Immobilie auf dem Ansichtsmodell zu, wo die anzeigt, ScrollViewer sollte sein? Es ist nicht klar, an was Sie das VerticalOffset binden möchten? – AnthonyWJones

Antwort

3

Da Sie ein ViewModel verwenden, nehme ich an, dass die "Aktion, die bewirkt, dass ScrollViewer neue Inhalte lädt", eine Folge von Änderungen ist, die innerhalb oder im ViewModel vorgenommen wurden. In diesem Fall würde ich dem ViewModel ein Ereignis hinzufügen, das bei jeder Änderung ausgelöst wird.

Ihre Ansicht kann einen Handler für dieses Ereignis hinzufügen und ScrollToVerticalPosition für den ScrollViewer aufrufen, wenn dieser ausgelöst wird.

4

Die folgende Blog-Post stellt ein Verhalten angebracht, die die vertikale/horizontale Versätze eines Scroll aussetzt, so dass Sie an sie binden können, oder sich im Code festgelegt:

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

Dies ermöglicht das folgende Markup :

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

Ich würde gerne einen Artikel sehen (Ich brauche Wpf-Lösung, um scrollviewer zu binden), aber die Verbindung ist falsch. – Sinatr

+0

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

+0

@Thomas danke - Ich habe den Link aktualisiert – ColinE

0

Ich habe die @ ColinE-Lösung vereinfacht. Anstatt mich an das Ereignis zu hängen, hake ich mich an das Ereignis ScrollViewer.ScrollChanged. Also, 1. Es ist nicht notwendig, die ScrollBar im visuellen Baum und 2. wird in einigen Übergangszuständen, wenn der Inhalt der ScrollViewer ändert sich geändert, und ich möchte nicht diese Zustände zu fangen.

ich meinen Code für die VerticalOffset zu veröffentlichen, die HorizontalOffset ist ähnlich:

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

Und es in der XAML verwenden:

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