2010-12-02 27 views
5

J'ai actuellement deux ScrollViewer contenant des vues alternatives de la même collection. J'ai lié le défilement des deux scrollviewers ensemble en manipulant l'événement ScrollChanged et en utilisant ScrollToVerticalOffset. Pour des raisons de présentation, j'ai placé les deux barres de défilement ScrollViewer sur cachées et je veux les contrôler toutes les deux à partir d'un ScrollBar séparé.Comment lier scrollbar et scrollviewer

Cela ne semble pas simple. Je me souviens d'avoir vu un blog à ce sujet il y a quelques mois, mais je ne le retrouve plus. Est-ce que n'importe qui peut me diriger dans la direction de quelques ressources utiles ou me donner une poussée dans la bonne direction à la façon dont elle pourrait être accomplie.

Merci d'avance.

Répondre

7

Ok, résolu ceci. Était en fait assez simple.

Avez depuis trouvé Wpf binding to a function, qui devrait aider quelqu'un d'autre intéressé. Son VB mais devrait être assez clair.

Vive

ci-dessus: De plus, je ScrollBar et passé sous-classé dans le ScrollViewer que je voulais lier. Cela semble fonctionner.

public class ScrollViewerBoundScrollBar : ScrollBar 
{ 
    private ScrollViewer _scrollViewer; 
    public ScrollViewer BoundScrollViewer { get { return _scrollViewer; } set { _scrollViewer = value; UpdateBindings(); } } 

    public ScrollViewerBoundScrollBar(ScrollViewer scrollViewer, Orientation o) : base() 
    { 
     this.Orientation = o; 
     BoundScrollViewer = _scrollViewer; 
    } 

    public ScrollViewerBoundScrollBar() : base() 
    { 
    } 

    private void UpdateBindings() 
    { 
     this.AddHandler(ScrollBar.ScrollEvent, new ScrollEventHandler(OnScroll)); 
     _scrollViewer.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(BoundScrollChanged)); 
     this.Minimum = 0; 
     if (Orientation == Orientation.Horizontal) 
     { 
      this.SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableWidth") { Source = _scrollViewer, Mode = BindingMode.OneWay })); 
      this.SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportWidth") { Source = _scrollViewer, Mode = BindingMode.OneWay })); 
     } 
     else 
     { 
      this.SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableHeight") { Source = _scrollViewer, Mode = BindingMode.OneWay })); 
      this.SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportHeight") { Source = _scrollViewer, Mode = BindingMode.OneWay })); 
     } 
     this.LargeChange = 242; 
     this.SmallChange = 16; 
    } 

    public void BoundScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     switch (this.Orientation) 
     { 
      case Orientation.Horizontal: 
       this.Value = e.HorizontalOffset; 
       break; 
      case Orientation.Vertical: 
       this.Value = e.VerticalOffset; 
       break; 
      default: 
       break; 
     } 
    } 

    public void OnScroll(object sender, ScrollEventArgs e) 
    { 
     switch(this.Orientation) 
     { 
      case Orientation.Horizontal: 
       this.BoundScrollViewer.ScrollToHorizontalOffset(e.NewValue); 
       break; 
      case Orientation.Vertical: 
       this.BoundScrollViewer.ScrollToVerticalOffset(e.NewValue); 
       break; 
      default: 
       break; 
     } 
    } 
} 
+0

+1 a parfaitement fonctionné. THX! –

11

Super, juste ce dont j'avais besoin. J'ai étendu un peu pour que le scrollviewer puisse être défini à partir de xaml en utilisant une propriété de dépendance. En XAML:

<local:BindableScrollBar BoundScrollViewer ="{Binding ElementName=ScrollViewer}" Orientation="Vertical" /> 

code:

/// <summary> 
/// An extended scrollbar that can be bound to an external scrollviewer. 
/// </summary> 
public class BindableScrollBar : ScrollBar 
{ 
    public ScrollViewer BoundScrollViewer 
    { 
     get { return (ScrollViewer)GetValue(BoundScrollViewerProperty); } 
     set { SetValue(BoundScrollViewerProperty, value); } 
    } 

    // Using a DependencyProperty as the backing store for BoundScrollViewer. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty BoundScrollViewerProperty = 
     DependencyProperty.Register("BoundScrollViewer", typeof(ScrollViewer), typeof(BindableScrollBar), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnBoundScrollViewerPropertyChanged))); 

    private static void OnBoundScrollViewerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     BindableScrollBar sender = d as BindableScrollBar; 
     if (sender != null && e.NewValue != null) 
     { 
      sender.UpdateBindings(); 
     } 
    } 



    /// <summary> 
    /// Initializes a new instance of the <see cref="BindableScrollBar"/> class. 
    /// </summary> 
    /// <param name="scrollViewer">The scroll viewer.</param> 
    /// <param name="o">The o.</param> 
    public BindableScrollBar(ScrollViewer scrollViewer, Orientation o) 
     : base() 
    { 
     this.Orientation = o; 
     BoundScrollViewer = scrollViewer; 
    } 

    /// <summary> 
    /// Initializes a new instance of the <see cref="BindableScrollBar"/> class. 
    /// </summary> 
    public BindableScrollBar() : base() { } 

    private void UpdateBindings() 
    { 
     AddHandler(ScrollBar.ScrollEvent, new ScrollEventHandler(OnScroll)); 
     BoundScrollViewer.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(BoundScrollChanged)); 
     Minimum = 0; 
     if (Orientation == Orientation.Horizontal) 
     { 
      SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableWidth") { Source = BoundScrollViewer, Mode = BindingMode.OneWay })); 
      SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportWidth") { Source = BoundScrollViewer, Mode = BindingMode.OneWay })); 
     } 
     else 
     { 
      this.SetBinding(ScrollBar.MaximumProperty, (new Binding("ScrollableHeight") { Source = BoundScrollViewer, Mode = BindingMode.OneWay })); 
      this.SetBinding(ScrollBar.ViewportSizeProperty, (new Binding("ViewportHeight") { Source = BoundScrollViewer, Mode = BindingMode.OneWay })); 
     } 
     LargeChange = 242; 
     SmallChange = 16; 
    } 

    private void BoundScrollChanged(object sender, ScrollChangedEventArgs e) 
    { 
     switch (this.Orientation) 
     { 
      case Orientation.Horizontal: 
       this.Value = e.HorizontalOffset; 
      break; 
      case Orientation.Vertical: 
       this.Value = e.VerticalOffset; 
       break; 
      default: 
       break; 
     } 
    } 

    private void OnScroll(object sender, ScrollEventArgs e) 
    { 
     switch (this.Orientation) 
     { 
      case Orientation.Horizontal: 
       this.BoundScrollViewer.ScrollToHorizontalOffset(e.NewValue); 
       break; 
      case Orientation.Vertical: 
       this.BoundScrollViewer.ScrollToVerticalOffset(e.NewValue); 
       break; 
      default: 
       break; 
     } 
    } 
} 
+0

merci! cela fonctionne comme un charme :) – Arseny

+0

comment puis-je lier le bindablescrollbar à un élément de modèle une fois que le modèle est appliqué? Mon autre scrollviewer n'existe pas encore lorsque la barre de défilement associable est créée, de sorte que l'élément n'est pas lié. –

+0

+1 vous les gars rock! –