我正在使用包含消息的ListView创建聊天应用程序。发送/接收新消息时,ListView应该滚动到新消息。
我正在使用MVVM,所以ListView看起来像
<ScrollViewer>
<ItemsControl Source="{Binding Messages}" />
</ScrollViewer>
我该怎么做?
编辑:我试图使此版本在创建行为之前的周年更新之前的版本中。这是我到目前为止所拥有的:
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 Community Toolkit中的VisualTreeExtensions
但是,调用TransformPoint之后的位置始终返回 {0, 0}
我究竟做错了什么?
从Windows 10版本1607开始,您可以使用ItemsStackPanel
。ItemsUpdatingScrollMode
值KeepLastItemInView
,这似乎是最自然的工作。
MS UWP文档(2017-2-8)中有一个``反向列表''示例,可以归结为以下XAML:
<ListView Source="{Binding Messages}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel
VerticalAlignment="Bottom"
ItemsUpdatingScrollMode="KeepLastItemInView"
/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
附带说明一下,是的,我同意您可能要摆脱a,ScrollViewer
因为它作为ListView
包装是多余的。
更新:
KeepLastItemInView
对于“周年纪念版”之前针对Windows 10的应用程序不可用。在这种情况下,确保列表在更改项目集合后始终显示最后一个项目的一种方法是覆盖OnItemsChanged
并调用ScrollIntoView
。基本实现如下所示:
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());
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句