簡體   English   中英

ListView滾動到最后一項WPF C#

[英]ListView scroll to last item WPF C#

如何使滾動規則始終在ListView自動結束時沒有焦點在WPF?

你可以使用它,它為我工作:

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

如果您需要更高級的細節,可以參考這篇文章

由於@ pduncan的答案不包含實際代碼,因此這里是他們發布的鏈接中的代碼,只是對我進行了一些小修改:

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;
        }
    }
}

我修改它以使用MoveCurrentToLast而不是使用listBox.Items[listBox.Items.Count - 1];獲取最后一項listBox.Items[listBox.Items.Count - 1]; 這樣做的原因(除了有點清潔之外)是有一個邊緣情況,如果你在列表中有重復的項目,然后獲取listBox.Items.Count - 1然后滾動到該項目可能不會滾動到您列表的末尾(它甚至可以向相反的方向滾動!)。 它會將您滾動到該項的第一個實例。

@pduncan和@MattBurland的答案都有一些問題,主要是他們無法正確注銷行為。

此實現將處理程序存儲在另一個附加屬性中,以便您可以通過綁定來打開和關閉行為。

請注意,這適用於ListView 如果您使用的是ListBox ,請將ListView出現更改為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;
        }
    }
}

像這樣使用它:

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

我也把它變成了一個靜態類,因為你不需要實例化它(它也不需要從DependencyObject派生)。 INotifyCollectionChanged已更改,因此錯誤表現為INotifyCollectionChanged異常,而不是NRE。

使用附加財產。 本文將向您展示如何: http//michlg.wordpress.com/2010/01/17/listbox-automatically-scroll-to-bottom/

對我來說,如果列表框中的每個記錄都不同,這些工作。 如果它們是相同的,它只會滾動到匹配的第一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM