滚动到UWP的ListView中的新项目 [英] Scroll to new item in ListView for UWP

查看:74
本文介绍了滚动到UWP的ListView中的新项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用包含消息的ListView创建聊天应用程序.发送/接收新邮件时,ListView应滚动到新邮件.

I'm creating a chat application with a ListView that contains the messages. When a new message is sent/received, the ListView should scroll to the new message.

我正在使用MVVM,所以ListView看起来像

I'm using MVVM, so the ListView looks like

<ScrollViewer>
    <ItemsControl Source="{Binding Messages}" />
</ScrollViewer>

我该怎么办?

我试图在创建行为"的周年更新"之前的版本中进行此操作.这是我到目前为止的内容:

I tried to make this work in versions prior to the Anniversary Update creating a Behavior. This is what I have so far:

public class FocusLastBehavior : Behavior<ItemsControl>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Items.VectorChanged += ItemsOnVectorChanged;
    }

    private void ItemsOnVectorChanged(IObservableVector<object> sender, IVectorChangedEventArgs @event)
    {
        var scroll = VisualTreeExtensions.FindVisualAscendant<ScrollViewer>(AssociatedObject);
        if (scroll == null)
        {
            return;
        }

        var last = AssociatedObject.Items.LastOrDefault();

        if (last == null)
        {
            return;
        }

        var container = AssociatedObject.ContainerFromItem(last);


        ScrollToElement(scroll, (UIElement)container);
    }

    private static void ScrollToElement(ScrollViewer scrollViewer, UIElement element,
        bool isVerticalScrolling = true, bool smoothScrolling = true, float? zoomFactor = null)
    {
        var transform = element.TransformToVisual((UIElement)scrollViewer.Content);
        var position = transform.TransformPoint(new Point(0, 0));

        if (isVerticalScrolling)
        {
            scrollViewer.ChangeView(null, position.Y, zoomFactor, !smoothScrolling);
        }
        else
        {
            scrollViewer.ChangeView(position.X, null, zoomFactor, !smoothScrolling);
        }
    }
}

代码使用了 UWP社区工具包

但是,调用TransformPoint之后的位置始终返回{0, 0}

However, the position after the call to TransformPoint always returns {0, 0}

我在做什么错了?

推荐答案

从Windows 10版本1607开始,您可以使用

As of Windows 10, version 1607 you can use ItemsStackPanel.ItemsUpdatingScrollMode with the value KeepLastItemInView, which seems like the most natural fit for the job.

有一个反向列表" MS UWP文档(2017-2-8)中的示例将归结为以下XAML:

There is an "Inverted Lists" example in MS UWP docs (2017-2-8) that would boil down to this XAML:

<ListView Source="{Binding Messages}">
   <ListView.ItemsPanel>
       <ItemsPanelTemplate>
           <ItemsStackPanel
               VerticalAlignment="Bottom"
               ItemsUpdatingScrollMode="KeepLastItemInView"
           />
       </ItemsPanelTemplate>
   </ListView.ItemsPanel>
</ListView>

顺便说一句,是的,我同意您可能想要摆脱ScrollViewer的想法,因为它作为ListView包装器是多余的.

On a side note, yes, I'd agree that you may want to get rid of a ScrollViewer as it's redundant as a ListView wrapper.

更新:

KeepLastItemInView不适用于周年纪念版"之前针对Windows 10的应用程序.如果是这种情况,确保更改项目集合后列表始终显示最后一个项目的一种方法是覆盖

KeepLastItemInView is not available for applications that target Windows 10 prior to the "Anniversary Edition". If that's the case, one way to make sure that a list always displays the last item after item collection is changed is to override OnItemsChanged and call ScrollIntoView. A basic implementation would look like this:

using System.Linq;
using Windows.UI.Xaml.Controls;

public class ChatListView : ListView
{
    protected override void OnItemsChanged(object e)
    {
        base.OnItemsChanged(e);
        if(Items.Count > 0) ScrollIntoView(Items.Last());
    }
}

这篇关于滚动到UWP的ListView中的新项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆