かずきのBlog@hatena

日本マイクロソフトに勤めています。このブログは個人ブログなので、ここに書いている内容は個人的な意見で会社の公式見解ではない点にご注意ください。好きなものは XAML と C# 。苦手なものは型の無い言語です。

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