2010-12-02 2 views
5

현재 동일한 컬렉션에 대한 대체보기가 포함 된 두 개의 ScrollViewer가 있습니다. ScrollChanged 이벤트를 처리하고 ScrollToVerticalOffset을 사용하여 두 스크롤 뷰어의 스크롤을 함께 묶었습니다.스크롤바와 스크롤 뷰어를 연결하는 방법

프리젠 테이션 이유로 ScrollViewer 스크롤 막대를 모두 숨김으로 설정하고 별도의 스크롤 막대에서 두 스크롤 막대를 모두 제어하려고합니다.

이것은 간단하지 않은 것처럼 보입니다. 나는 그것에 대해 몇 달 전에 블로그를보고 기억하지만, 나는 그것을 다시 찾을 수 없다.

누구나 유용한 정보를 얻을 수있는 방향으로 나를 안내하거나 나에게 어떻게 올바른 방향으로 나아갈 수 있습니까?

미리 감사드립니다.

답변

7

좋아, 해결했습니다. 사실 아주 간단했습니다.

이후 관심있는 다른 사용자에게 도움이되는 Wpf binding to a function이 발견되었습니다. 그것의 VB지만 충분히 명확해야합니다.

환호 위 또한

: 나는 스크롤 막대를 서브 클래스 내가 바인딩하고 싶었에서 ScrollViewer 전달. 괜찮습니다.

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

한 완벽했다. 고마워! 덕분에 –

11

내가 필요한 것. scrollviewer가 xaml에서 종속성 속성을 사용하여 설정할 수 있도록 조금 확장했습니다. XAML에서 :

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

코드 :

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

! 그것은 매력처럼 작동합니다 :) – Arseny

+0

일단 템플릿이 적용되면 템플릿 항목에 bindablescrollbar를 바인딩 할 수 있습니까? 바인딩 가능한 스크롤 막대가 만들어 질 때 내 다른 scrollviewer가 아직 존재하지 않으므로 항목이 바인딩되지 않습니다. –

+0

+1 놈들 아! –