かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Universal Windows Platform appのListViewで追加されたアイテムに自動でスクロールさせたい

ということをしたいというケースがありました。

やり方としては、ItemsSourceがINotifyCollectionChangedだったら追加されたCollectionChangedを購読して追加された要素に対してScrollIntoViewしてやるだけです。 とりあえず、こういうBehaviorを作ってListViewにぽとっと落として実現しました。

public class ScrollBottomBehavior : DependencyObject, IBehavior
{
    public DependencyObject AssociatedObject
    {
        get;
        set;
    }

    private INotifyCollectionChanged currentItemsSource;

    public void Attach(DependencyObject associatedObject)
    {
        this.AssociatedObject = associatedObject;
        var lv = this.AssociatedObject as ListView;
        lv.DataContextChanged += (_, __) =>
        {
            if (this.currentItemsSource != null)
            {
                this.currentItemsSource.CollectionChanged -= this.CurrentItemsSource_CollectionChanged;
            }
            this.currentItemsSource = lv.ItemsSource as INotifyCollectionChanged;
            if (this.currentItemsSource != null)
            {
                this.currentItemsSource.CollectionChanged += this.CurrentItemsSource_CollectionChanged;
            }
        };
    }

    private void CurrentItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action != NotifyCollectionChangedAction.Add)
        {
            return;
        }

        var item = e.NewItems.Cast<ChatMessageViewModel>().First();
        ((ListView)this.AssociatedObject).ScrollIntoView(item);
    }

    public void Detach()
    {
        if (this.currentItemsSource != null)
        {
            this.currentItemsSource.CollectionChanged -= this.CurrentItemsSource_CollectionChanged;
            this.currentItemsSource = null;
        }
    }
}