2009-07-03 40 views
10

Trong WPF, tôi biết tôi có thể sử dụng ListView.ScrollIntoView để cuộn một mục cụ thể vào chế độ xem, nhưng nó sẽ luôn làm số lượng ít nhất của cuộn để mục được hiển thị.Danh sách cuộnViewItem ở trên cùng của một ListView

Tôi làm cách nào để di chuyển để mục tôi muốn hiển thị được cuộn lên đầu Chế độ xem danh sách?

Tôi đã nghĩ đến việc gọi ScrollIntoView hai lần, một lần cho mục tôi muốn ở trên cùng và một lần cho mục được hiển thị lần cuối, nhưng tôi không biết cách tìm mục cuối cùng được hiển thị.

Trả lời

14

Chúng tôi có thể thực hiện việc này bằng cách lấy số ScrollViewer có trong ControlTemplate của ListView. Nếu bạn có quyền truy cập vào ScrollViewer thì có a lot các phương thức cuộn khác nhau được hiển thị.

Đầu tiên, chúng ta có thể tạo ra một ListView mà chúng tôi muốn thêm hiệu ứng này để:

<ListView ItemsSource="{Binding Percents}" 
     SelectionChanged="OnSelectionChanged" 
     x:Name="uiListView"/> 


public List<int> Percents { get; set; } 

public Window1() 
{ 
    InitializeComponent(); 

    Percents = new List<int>(); 
    for (int i = 1; i <= 100; i++) 
    { 
     Percents.Add(i); 
    } 
    this.DataContext = this; 
} 

Chúng tôi cũng sẽ cần một cái gì đó mà chúng ta có thể sử dụng để có được những ScrollViewer từ ListView. Tôi đã sử dụng một cái gì đó tương tự như thế này trước khi làm việc với cuộn tùy chỉnh, và chúng tôi có thể sử dụng nó ở đây là tốt.

public static DependencyObject GetScrollViewer(DependencyObject o) 
{ 
    if (o is ScrollViewer) 
    { return o; } 

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) 
    { 
     var child = VisualTreeHelper.GetChild(o, i); 

     var result = GetScrollViewer(child); 
     if (result == null) 
     { 
      continue; 
     } 
     else 
     { 
      return result; 
     } 
    } 

    return null; 
} 

Bây giờ, chúng tôi chỉ cần xử lý sự kiện SelectionChanged. Vì chúng tôi đang cố gắng cuộn một mục lên đầu danh sách, tùy chọn tốt nhất là cuộn xuống dưới cùng rồi cuộn lại lên mục đã chọn của chúng tôi. Như bạn đã nói, ScrollIntoView sẽ cuộn cho đến khi mục được hiển thị, và vì vậy khi mục đã chọn đạt đến đỉnh khi nó cuộn lên, nó sẽ dừng lại cho chúng tôi với mục đã chọn của chúng tôi ở đầu danh sách.

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer; 
    scrollViewer.ScrollToBottom(); 

    uiListView.ScrollIntoView(e.AddedItems[0]); 
} 
+0

Hoàn hảo :) Cảm ơn – Ray

+0

Nó hoạt động như một sự quyến rũ đối với tôi. Cảm ơn !!! – thowa

+1

Lưu ý, nếu bạn đang sử dụng Bộ công cụ mở rộng WPF, bạn có thể lấy ScrollViewer trong một dòng mã: VisualTreeHelperEx.FindDescendantByType (YourListView); –

0

Đây là một thay thế cho câu trả lời của @rmoore rằng tránh di chuyển xuống đáy. Cũng lưu ý rằng điều này chỉ hữu ích trong trường hợp SelectionMode=Single.

Trong trường hợp ScrollViewer.CanContentScroll=TrueScrollViewer có thể cuộn trực tiếp đến SelectedIndex.

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer;  
    scrollViewer.ScrollToVerticalOffset(listView.SelectedIndex); 
} 

và trong trường hợp ScrollViewer.CanContentScroll=False một số XAML bổ sung là cần thiết:

<ListView ScrollViewer.CanContentScroll="False" ItemsSource="{Binding Percents}" x:Name="uiListView"> 
    <ListView.ItemContainerStyle> 
     <Style TargetType="{x:Type ListViewItem}"> 
      <EventSetter Event="Selected" Handler="OnSelected"/> 
     </Style> 
    </ListView.ItemContainerStyle> 
</ListView> 

ScrollViewer có thể di chuyển đến dọc bù đắp của phía trên cùng của ListViewItem.

private void OnSelected(object sender, RoutedEventArgs e) 
{ 
    ScrollViewer scrollViewer = GetScrollViewer(uiListView) as ScrollViewer;  

    ListViewItem listViewItem = (ListViewItem)e.Source; 
    Point offset = listViewItem.TranslatePoint(new Point(), scrollViewer); 
    scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset.Y); 
} 
Các vấn đề liên quan