2010-09-28 34 views

Trả lời

2

Sử dụng thuộc tính được đính kèm. Bài viết này sẽ chỉ cho bạn cách: http://michlg.wordpress.com/2010/01/17/listbox-automatically-scroll-to-bottom/

+0

Đây là giải pháp chính xác hơn. Nó cũng ấn tượng rằng một cái gì đó đã được thực hiện trong WPF chỉ với 37 dòng (cộng với ý kiến). – Grault

+0

Liên kết bị lỗi thời, sẽ rất hữu ích khi bao gồm mã * trong câu trả lời của bạn * –

3

bạn có thể sử dụng này, nó làm việc cho tôi:

this.myListView.ScrollIntoView (myListView.Items [myListView.Items.Count-1]);

nếu bạn cần chi tiết cao cấp hơn bạn có thể refere này post

1

Kể từ khi câu trả lời @ pduncan của không bao gồm mã thực tế, đây là mã từ liên kết họ đăng tải chỉ với một thay đổi nhỏ từ tôi:

public class ListBoxExtenders : DependencyObject 
{ 
    public static readonly DependencyProperty AutoScrollToEndProperty = DependencyProperty.RegisterAttached("AutoScrollToEnd", typeof(bool), typeof(ListBoxExtenders), new UIPropertyMetadata(default(bool), OnAutoScrollToEndChanged)); 

    /// <summary> 
    /// Returns the value of the AutoScrollToEndProperty 
    /// </summary> 
    /// <param name="obj">The dependency-object whichs value should be returned</param> 
    /// <returns>The value of the given property</returns> 
    public static bool GetAutoScrollToEnd(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(AutoScrollToEndProperty); 
    } 

    /// <summary> 
    /// Sets the value of the AutoScrollToEndProperty 
    /// </summary> 
    /// <param name="obj">The dependency-object whichs value should be set</param> 
    /// <param name="value">The value which should be assigned to the AutoScrollToEndProperty</param> 
    public static void SetAutoScrollToEnd(DependencyObject obj, bool value) 
    { 
     obj.SetValue(AutoScrollToEndProperty, value); 
    } 

    /// <summary> 
    /// This method will be called when the AutoScrollToEnd 
    /// property was changed 
    /// </summary> 
    /// <param name="s">The sender (the ListBox)</param> 
    /// <param name="e">Some additional information</param> 
    public static void OnAutoScrollToEndChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) 
    { 
     var listBox = s as ListBox; 
     if (listBox != null) 
     { 
      var listBoxItems = listBox.Items; 
      var data = listBoxItems.SourceCollection as INotifyCollectionChanged; 

      var scrollToEndHandler = new System.Collections.Specialized.NotifyCollectionChangedEventHandler(
       (s1, e1) => 
       { 
        if (listBox.Items.Count > 0) 
        { 
         listBoxItems.MoveCurrentToLast(); 
         listBox.ScrollIntoView(listBoxItems.CurrentItem); 
        } 
       }); 

      if ((bool)e.NewValue) 
       data.CollectionChanged += scrollToEndHandler; 
      else 
       data.CollectionChanged -= scrollToEndHandler; 
     } 
    } 
} 

Tôi đã sửa đổi nó để sử dụng MoveCurrentToLast thay vì nhận mục cuối cùng với listBox.Items[listBox.Items.Count - 1];. Lý do cho điều này (ngoài việc dọn dẹp một chút) là có một trường hợp cạnh nếu bạn có các mục trùng lặp trong danh sách, sau đó nhận được listBox.Items.Count - 1 và sau đó cuộn đến mục đó có thể không cuộn bạn đến cuối danh sách (nó thậm chí có thể cuộn bạn theo hướng ngược lại!). Thay vào đó, nó sẽ chuyển bạn đến phiên bản đầu tiên của mục đó.

0

Các câu trả lời từ @pduncan và @MattBurland đều có một số vấn đề, chủ yếu là chúng không hủy đăng ký hành vi đúng cách.

Triển khai này lưu trữ trình xử lý trong thuộc tính được đính kèm khác để bạn có thể bật và tắt hành vi, có thể thông qua một ràng buộc.

Lưu ý rằng điều này áp dụng cho ListView. Nếu bạn đang sử dụng ListBox, hãy thay đổi các lần xuất hiện của ListView thành ListBox.

public static class ListViewExtensions 
{ 
    public static readonly DependencyProperty AutoScrollToEndProperty = DependencyProperty.RegisterAttached("AutoScrollToEnd", typeof(bool), typeof(ListViewExtensions), new UIPropertyMetadata(OnAutoScrollToEndChanged)); 
    private static readonly DependencyProperty AutoScrollToEndHandlerProperty = DependencyProperty.RegisterAttached("AutoScrollToEndHandler", typeof(NotifyCollectionChangedEventHandler), typeof(ListViewExtensions)); 

    public static bool GetAutoScrollToEnd(DependencyObject obj) => (bool)obj.GetValue(AutoScrollToEndProperty); 
    public static void SetAutoScrollToEnd(DependencyObject obj, bool value) => obj.SetValue(AutoScrollToEndProperty, value); 

    private static void OnAutoScrollToEndChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) 
    { 
     var listView = s as ListView; 

     if (listView == null) 
      return; 

     var source = (INotifyCollectionChanged)listView.Items.SourceCollection; 

     if ((bool)e.NewValue) 
     { 
      NotifyCollectionChangedEventHandler scrollToEndHandler = delegate 
      { 
       if (listView.Items.Count <= 0) 
        return; 
       listView.Items.MoveCurrentToLast(); 
       listView.ScrollIntoView(listView.Items.CurrentItem); 
      }; 

      source.CollectionChanged += scrollToEndHandler; 

      listView.SetValue(AutoScrollToEndHandlerProperty, scrollToEndHandler); 
     } 
     else 
     { 
      var handler = (NotifyCollectionChangedEventHandler)listView.GetValue(AutoScrollToEndHandlerProperty); 

      source.CollectionChanged -= handler; 
     } 
    } 
} 

Sử dụng nó như thế này:

<ListView local:ListViewExtensions.AutoScrollToEnd="{Binding Path=AutoScroll}"> 

Tôi cũng đã làm cho nó một lớp tĩnh, khi bạn không cần phải khởi tạo nó (và cũng không cần phải xuất phát từ DependencyObject). Các diễn viên để INotifyCollectionChanged đã được thay đổi để lỗi bề mặt như trường hợp ngoại lệ đúc, không NREs.

0

Đối với tôi, các công việc này nếu mỗi bản ghi trong hộp danh sách khác nhau. Nếu chúng giống nhau, nó chỉ cuộn đến cột đầu tiên phù hợp.

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