2010-01-26 5 views
0

enter code here 코드에서 ScrollToVerticalOffset 메서드를 호출 할 때마다 ScrollViewer가 세로로 스크롤되지 않습니다.Silverlight ScrollViewer Not Scrolling

기본적으로 ScrollViewer가 포함 된 내 View (UserControl)이 있습니다. VerticalOffset을 특정 값으로 설정하는 View의 코드 숨김에서 이벤트를 트리거하는 내 ViewModel에서 액션을 호출합니다.

우선, 나는 이것이 매우 추한 것을 알고 있습니다. 이상 적으로는 ViewModel의 속성에 바인딩 할 수있는 부착 가능한 속성이 있으면 좋겠다. 설정하면 VerticalOffset 속성 (읽기 전용 인 경우)이 업데이트되고 ScrollViewer가 스크롤되도록합니다.

ScrollViewer에는 동적 콘텐츠가 포함되어 있습니다. 따라서 사용자가 ScrollViewer에서 내용을보고 반쪽으로 스크롤 한 다음 버튼을 클릭하면 새 내용이 ScrollViewer에로드됩니다. 문제는 ScrollViewer의 수직 오프셋이 재설정되지 않으므로 사용자가 스크롤하여 내용을 읽어야한다는 것입니다. 그래서, 제 솔루션은 ViewModel에서 수직 오프셋을 제어 할 수 있어야했습니다. 그리고 저는 뇌를 깨고 실행 가능한 솔루션을 찾을 수 없으므로 도움을받을 사람을 찾고 있습니다.

덧붙여서 - 나는 attachable 속성을 위해 클래스의 코드를 포함 시켰습니다. 이 속성은 내 ViewModel의 속성에 바인딩됩니다. ViewModel에서 속성을 설정하면이 클래스의 PropertyChanged 콜백 메서드가 올바르게 트리거되고,이 클래스는 ScrollViewer에 대한 ScrollToVerticalOffset 메서드를 호출하지만 ScrollViewer는 여전히 스크롤하지 않습니다. 나는에서 ScrollViewer와 뷰 모델과는 매우 작은 (또는 아무것도)을 가져야한다 "보기"엔티티로 VerticalScrollOffset 모두의 생각으로

public class ScrollViewerHelper 
{ 
    public static readonly DependencyProperty BindableOffsetProperty = 
    DependencyProperty.RegisterAttached("BindableOffset", typeof(double), typeof(ScrollViewerHelper), 
    new PropertyMetadata(OnBindableOffsetChanged)); 

    public static double GetBindableOffset(DependencyObject d) 
    { 
     return (double)d.GetValue(BindableOffsetProperty); 
    } 

    public static void SetBindableOffset(DependencyObject d, double value) 
    { 
     d.SetValue(BindableOffsetProperty, value); 
    } 

    private static void OnBindableOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ScrollViewer scrollViewer = d as ScrollViewer; 

     if (scrollViewer != null) 
     { 
      scrollViewer.ScrollToVerticalOffset((double)e.NewValue); 
     } 
    } 
} 
+0

왜이 솔루션이 작동하지 않을지 모르겠다 ... 새로운 요소가 추가 될 때마다 요소 패널의 위쪽 또는 아래쪽에 뷰포트를 고정하려고합니까? 새 요소를 추가 할 때마다 OnBindableOffsetChanged가 호출되는지 확실합니까? 매번 뷰 모델 속성을 0.0으로 설정하는 경우 (맨 위로 스크롤) 처음으로 호출 된 이유와 다시는 볼 수없는 이유를 확인할 수 있습니다. –

답변

0

이 방법은, 내 의견으로는 약간 펑키입니다. 이것은 MVVM을 너무 많이 강요하고 첨부 된 종속성 속성을 만드는 데 많은 추가 작업을 만들고 기본적으로 ScrollViewer의 읽기 전용 VerticalScrollOffset과 동기화 된 바운드 Offset ViewModel 속성을 유지하려고하는 것처럼 보입니다.

정확하게는이 아니지만 일부 동적 요소가 ScrollViewer의 기본 패널에 추가 될 때 지정한 오프셋으로 스크롤하려고하는 것처럼 들립니다. 개인적으로, 나는 단지 내 View에서 약간의 코드로이 동작을 처리하고 ViewModel에 묶는 것을 잊어 버리고 싶습니다.

Silverlight 3에서 이러한 유형의 작업을 수행하는 정말 좋은 방법 중 하나는 블렌드 동작입니다. C#에서 약간의 비헤이비어 코드를 작성한 다음 XAML의 요소에 선언적으로 첨부 할 수 있습니다. 이렇게하면 재사용이 가능하며 코드 숨김에서 벗어날 수 있습니다. 프로젝트는 혼합 SKD의 일부인 System.Windows.Interactivity DLL을 참조해야합니다. 여기

는 당신이를 스크롤에서 ScrollViewer에 추가 할 수있는 간단한 혼합 행동의 간단한 예제 상기에서 ScrollViewer의 기본 내용의 크기가 변경 될 때마다 지정된 오프셋 (offset) : 그런 다음이 동작을 적용 할 수

public class ScrollToOffsetBehavior : Behavior<ScrollViewer> 
{ 
    private FrameworkElement contentElement = null; 

    public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register(
     "Offset", 
     typeof(double), 
     typeof(ScrollToOffsetBehavior), 
     new PropertyMetadata(0.0)); 

    public double Offset 
    { 
     get { return (double)GetValue(OffsetProperty); } 
     set { SetValue(OffsetProperty, value); } 
    } 

    protected override void OnAttached() 
    { 
     base.OnAttached(); 

     if (this.AssociatedObject != null) 
     { 
      this.AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded); 
     } 
    } 

    protected override void OnDetaching() 
    { 
     base.OnDetaching(); 

     if (this.contentElement != null) 
     { 
      this.contentElement.SizeChanged -= contentElement_SizeChanged; 
     } 

     if (this.AssociatedObject != null) 
     { 
      this.AssociatedObject.Loaded -= AssociatedObject_Loaded; 
     } 
    } 

    void AssociatedObject_Loaded(object sender, RoutedEventArgs e) 
    { 
     this.contentElement = this.AssociatedObject.Content as FrameworkElement; 

     if (this.contentElement != null) 
     { 
      this.contentElement.SizeChanged += new SizeChangedEventHandler(contentElement_SizeChanged); 
     } 
    } 

    void contentElement_SizeChanged(object sender, SizeChangedEventArgs e) 
    { 
     this.AssociatedObject.ScrollToVerticalOffset(this.Offset); 
    } 
} 

XAML에서에서 ScrollViewer에 (다시 위로 스크롤 오프셋 0으로 지정) : 이것은 당신은 항상 오프셋 때마다 콘텐츠 크기 변경으로 스크롤 할 것으로 가정 할 것이다

<ScrollViewer> 
     <i:Interaction.Behaviors> 
      <local:ScrollToOffsetBehavior Offset="0"/> 
     </i:Interaction.Behaviors> 
     ...Scroll Viewer Content... 
    </ScrollViewer> 

. 이것은 정확하게 당신이 찾고있는 것이 아닐지도 모르지만 이것은 행동을 사용하여 뷰에서 할 수있는 일의 예입니다.

관련 문제