2009-08-04 29 views
13

Tôi có một ScrollViewer có chứa một Grid với nhiều điều khiển trong đó. Người dùng có thể tab thông qua các điều khiển, nhưng cuối cùng họ tab để một điều khiển mà không phải là trong xem - vì vậy họ phải manully di chuyển để làm cho điều khiển có thể nhìn thấy một lần nữa.Làm thế nào tôi có thể làm cho Scrolllighter Silverlight cuộn để hiển thị điều khiển con bằng tiêu điểm?

Có cách nào để làm cho ScrollViewer cuộn tự động sao cho điều khiển tập trung luôn hiển thị. Nếu không, có cách nào tôi có thể thực hiện công việc này, không nghe được sự kiện GotFocus trên mọi điều khiển và sau đó cuộn ScrollViewer để làm cho điều khiển hiển thị?

Hiện nay tôi đang sử dụng Silverlight 2.

Trả lời

12

Tôi thử nghiệm này sử dụng Silverlight 3. Tôi không chắc chắn về SL2.

Đây là XAML của tôi:

<ScrollViewer Height="200" Width="200" KeyUp="ScrollViewer_KeyUp"> 
    <StackPanel> 
     <Button Content="1" Height="20" /> 
     <Button Content="2" Height="20" /> 
     <Button Content="3" Height="20" /> 
     <Button Content="4" Height="20" /> 
     <Button Content="5" Height="20" /> 
     <Button Content="6" Height="20" /> 
     <Button Content="7" Height="20" /> 
     <Button Content="8" Height="20" /> 
     <Button Content="9" Height="20" /> 
    <Button Content="10" Height="20" /> 
     <Button Content="11" Height="20" /> 
     <Button Content="12" Height="20" /> 
     <Button Content="13" Height="20" /> 
     <Button Content="14" Height="20" /> 
     <Button Content="15" Height="20" /> 
     <Button Content="16" Height="20" /> 
     <Button Content="17" Height="20" /> 
     <Button Content="18" Height="20" /> 
     <Button Content="19" Height="20" /> 
     <Button Content="20" Height="20" /> 
    </StackPanel> 
</ScrollViewer> 

Và đây là code-behind:

private void ScrollViewer_KeyUp(object sender, KeyEventArgs e) 
{ 
    ScrollViewer scrollViewer = sender as ScrollViewer; 
    FrameworkElement focusedElement = FocusManager.GetFocusedElement() as FrameworkElement; 
    GeneralTransform focusedVisualTransform = focusedElement.TransformToVisual(scrollViewer); 
    Rect rectangle = focusedVisualTransform.TransformBounds(new Rect(new Point(focusedElement.Margin.Left, focusedElement.Margin.Top), focusedElement.RenderSize)); 
    double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight); 
    scrollViewer.ScrollToVerticalOffset(newOffset); 
} 

Những gì tôi đã làm là bấm vào nút # 1 và tab cho đến khi tôi nhận được để nút # 20. Nó làm việc cho tôi. Hãy thử và cho tôi biết nó hoạt động như thế nào cho bạn.

+0

Cảm ơn - với một sửa đổi nhỏ, mà tôi sẽ đăng là câu trả lời, nó hoạt động rất độc đáo. Phương thức TransformBounds trên GeneralTransform dường như là một điều SL3. –

+0

Tôi biết đây là một bài đăng cũ, nhưng tôi đang cố gắng làm điều tương tự. Tôi đang sử dụng mã này nhưng giá trị Margin.Left và Margin.Top luôn là 0. – Jeremy

1

Tôi đã làm việc này, với sự giúp đỡ của câu trả lời của Kiril ở trên. Ngữ cảnh chung của việc này là tôi có các biểu mẫu có thể xác định người dùng trong ứng dụng của tôi và mã này được sử dụng để hiển thị các điều khiển trên biểu mẫu.

Chiến lược chung của tôi là thêm điều khiển vào lưới, sau đó tìm tất cả các con của ScrollViewer bằng VisualTreeHelper và thêm bộ xử lý sự kiện GotFocus vào mỗi điều khiển.

Khi điều khiển được lấy nét, một lần nữa bằng cách sử dụng VisualTreeHelper, tôi tìm kiếm cây trực quan để tìm điều khiển có cha mẹ là lưới đang được cuộn bởi ScrollViewer. Sau đó, tôi cuộn ScrollViewer để hiển thị điều khiển.

Dưới đây là đoạn code (gridRender là Lưới rằng các điều khiển được thêm vào):

private void AfterFormRendered() 
{ 
    var controls = VisualTreeHelperUtil.FindChildren<Control>(gridRender); 
    foreach (var ctrl in controls) 
    { 
     ctrl.GotFocus += CtrlGotFocus; 
    } 
} 

private void CtrlGotFocus(object sender, RoutedEventArgs e) 
{ 
    var ctrl = sender as Control; 
    var gridChildControl = VisualTreeHelperUtil.FindParentWithParent(ctrl, gridRender) as FrameworkElement; 

    if (gridChildControl != null) 
    { 
     // Ensure the control is scrolled into view in the ScrollViewer. 
     GeneralTransform focusedVisualTransform = gridChildControl.TransformToVisual(scrollViewer); 
     Point topLeft = focusedVisualTransform.Transform(new Point(gridChildControl.Margin.Left, gridChildControl.Margin.Top)); 
     Rect rectangle = new Rect(topLeft, gridChildControl.RenderSize); 
     double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);  

     scrollViewer.ScrollToVerticalOffset(newOffset); 
    } 
} 

Lưu ý: lớp VisualTreeHelperUtil là lớp của riêng tôi có thêm một số chức năng tìm kiếm hữu ích cho lớp VisualTreeHelper.

3

Chỉ cần tăng cường nhẹ. Vẫn cần phải làm điều này cho Silverlight 4 bằng cách này. Thay vì GotFocus cho mỗi điều khiển, bạn có thể xử lý GotFocus của chính scrollviewer và thực hiện nó chỉ một lần.

private void _ScrollViewer_GotFocus(object sender, RoutedEventArgs e) 
     { 
      FrameworkElement element = e.OriginalSource as FrameworkElement; 

      if (element != null) 
      { 
       ScrollViewer scrollViewer = sender as ScrollViewer; 
       scrollViewer.ScrollToVerticalOffset(GetVerticalOffset(element, scrollViewer)); 
      } 

     } 

     private double GetVerticalOffset(FrameworkElement child, ScrollViewer scrollViewer) 
     { 
      // Ensure the control is scrolled into view in the ScrollViewer. 
      GeneralTransform focusedVisualTransform = child.TransformToVisual(scrollViewer); 
      Point topLeft = focusedVisualTransform.Transform(new Point(child.Margin.Left, child.Margin.Top)); 
      Rect rectangle = new Rect(topLeft, child.RenderSize); 
      double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight); 
      return newOffset < 0 ? 0 : newOffset; // no use returning negative offset 
     } 
11

Bộ công cụ Silverlight chứa phương pháp "ScrollIntoView".

Thêm tham chiếu đến System.Windows.Controls.Toolkit.dll ans bạn sẽ có thể sử dụng mã bên dưới.

scrollViewer.ScrollIntoView(control);

Các vấn đề liên quan