2010-12-02 10 views
5

Actualmente tengo dos ScrollViewer que contienen vistas alternativas de la misma colección. He unido el desplazamiento de los dos visualizadores de desplazamiento mediante el manejo del evento ScrollChanged y el uso de ScrollToVerticalOffset.Cómo vincular scrollbar y scrollviewer

Por razones de presentación, he establecido las dos barras de desplazamiento de ScrollViewer ocultas y quiero controlarlas desde una barra de desplazamiento separada.

Esto parece no ser sencillo. Recuerdo haber visto un blog sobre esto hace unos meses, pero no puedo encontrarlo nuevamente.

¿Alguien me puede indicar algunos recursos útiles o darme un empujón en la dirección correcta de cómo se puede lograr?

Gracias de antemano.

Respuesta

7

Ok, resolvió esto. En realidad fue bastante sencillo.

Han encontrado desde Wpf binding to a function, que debería ayudar a cualquier otra persona interesada. Su VB pero debe ser lo suficientemente claro.

Saludos

más arriba: Me subclases ScrollBar y pasé en el ScrollViewer quería unirse. Parece que funciona bien.

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 funcionó a la perfección. ¡Gracias! –

11

Genial, justo lo que necesitaba. Amplié un poco para que el scrollviewer también se pueda establecer desde xaml usando una propiedad de dependencia. En xaml:

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

Código:

/// <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

gracias! funciona como un encanto :) – Arseny

+0

¿cómo puedo vincular el bindablescrollbar a un elemento de plantilla una vez que se aplica la plantilla? Mi otro scrollviewer aún no existe cuando se crea la barra de desplazamiento enlazable, por lo que el elemento no está vinculado. –

+0

+1 u chicos rock! –

Cuestiones relacionadas