收到新消息时,使ListView自动滚动到底部吗?

时间:2019-04-09 07:58:51

标签: listview xamarin.forms

我一直在使用this example在xamarin中构建一个移动应用程序以与我的聊天机器人进行交互。我遇到的问题是,显示bot和用户之间的消息的ListView在其中显示新消息时不会自动滚动到底部。这是代码:

<ContentPage.Content>
    <StackLayout Margin="5">
        <ListView x:Name="ChatListView"
            VerticalOptions="FillAndExpand"
            SelectedItem="{Binding SelectedMessage}"
            ItemsSource="{Binding BotMessages, Mode=TwoWay}"
            BackgroundColor="Azure"
            HasUnevenRows="True" 
            SeparatorVisibility="None"
            ItemTemplate="{StaticResource ChatDataTemplateSelector}"/>
        <StackLayout Orientation="Horizontal">
            <Entry Placeholder="Ask a question.."
                Margin="5"
                Keyboard="Chat"
                Text="{Binding CurrentMessage, Mode=TwoWay}"
                HorizontalOptions="FillAndExpand"
                Completed="Entry_Completed"/>
            <Button Text="Send" Command="{Binding SendCommand}"/>
        </StackLayout>
    </StackLayout>
</ContentPage.Content> 

是否有某种方法可以使收到新邮件时Listview自动滚动到底部?

1 个答案:

答案 0 :(得分:1)

要滚动到某个项目,您要做的就是:

ChatListView.ScrollTo(item, ScrollToPosition.MakeVisible, true);

如果您想要一个列表,当与可观察的集合一起使用时将自动滚动到新的/更新的项目,则可以尝试使用此扩展名:

namespace Your.Namespace.For.Custom.Controls
{
    public class AutoScrollListView : ListView
    {
        private INotifyCollectionChanged _previousObservableCollection;

        public AutoScrollListView(ListViewCachingStrategy cachingStrategy)
            : base(cachingStrategy)
        {
        }

        public AutoScrollListView()
            : base()
        {
        }

        protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            base.OnPropertyChanged(propertyName);

            if (propertyName == nameof(ItemsSource))
            {
                if (_previousObservableCollection != null)
                {
                    _previousObservableCollection.CollectionChanged -= OnItemsSourceCollectionChanged;
                    _previousObservableCollection = null;
                }

                if (ItemsSource is INotifyCollectionChanged newObservableCollection)
                {
                    _previousObservableCollection = newObservableCollection;
                    newObservableCollection.CollectionChanged += OnItemsSourceCollectionChanged;
                }
            }
        }

        private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)
            {
                foreach (var item in e.NewItems)
                {
                    // Scroll to the item that has just been added/updated to make it visible
                    ScrollTo(item, ScrollToPosition.MakeVisible, true);
                }
            }
        }
    }
}

要使用它,请记住将其命名空间添加到XAML文件中:

<Page 
    xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:custom="clr-namespace:Your.Namespace.For.Custom.Controls" 
    x:Class="Your.Namespace.YourPage">

    ...

    <ContentPage.Content>
        <StackLayout Margin="5">
            <custom:AutoScrollListView
                x:Name="ChatListView"
                VerticalOptions="FillAndExpand"
                SelectedItem="{Binding SelectedMessage}"
                ItemsSource="{Binding BotMessages, Mode=TwoWay}"
                BackgroundColor="Azure"
                HasUnevenRows="True" 
                SeparatorVisibility="None"
                ItemTemplate="{StaticResource ChatDataTemplateSelector}" />
            <StaLayout Orientation="Horizontal">
                <Entry 
                    Placeholder="Ask a question.." 
                    Margin="5" 
                    Keyboard="Chat"
                    Text="{Binding CurrentMessage, Mode=TwoWay}"
                    HorizontalOptions="FillAndExpand"
                    Completed="Entry_Completed"/>
                <Button Text="Send" Command="{Binding SendCommand}" />
            </StackLayout>
        </StackLayout>
    </ContentPage.Content> 

    ...

</Page>

请记住,如上所述,仅当属性ItemsSource绑定到可观察的集合时,此自定义列表才会自动滚动。

希望对您有帮助!