You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms中AutoScrollListView重复元素滚动异常问题求助

问题:ListView添加重复元素时自动滚动定位错误

我实现了继承自ListView的AutoScrollListView类,目的是添加元素时自动滚动到最新项。但遇到一个问题:添加重复元素时,控件会滚动到第一个出现的重复元素,而非刚添加的最新项。比如依次添加C#、Html、T-SQL、Python、PL-SQL、PL-SQL后,滚动停留在第一个PL-SQL,只有滚动动画但没定位到最后一个新增元素。

原实现代码:

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.End,true);
                
            }
        }
    }
}
解决方案

问题根源是ScrollTo(item, ...)通过元素的Equals方法匹配目标项,重复元素会被定位到第一个匹配实例,而非最新添加的项。改用索引定位即可解决,因为每个元素的索引是唯一的。

方法一:直接滚动到集合最后一项

修改OnItemsSourceCollectionChanged方法,通过集合总数量计算最后一个元素的索引:

private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)
    {
        if (ItemsSource is ICollection items && items.Count > 0)
        {
            ScrollTo(items.Count - 1, ScrollToPosition.End, true);
        }
    }
}

方法二:针对新增项的索引定位

如果一次添加多个元素,可利用NotifyCollectionChangedEventArgs中的NewStartingIndex和NewItems.Count计算最后一个新增元素的索引:

private void OnItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace)
    {
        var targetIndex = e.NewStartingIndex + e.NewItems.Count - 1;
        ScrollTo(targetIndex, ScrollToPosition.End, true);
    }
}

两种方式都能精准定位到最新添加的元素,避免重复元素导致的定位错误。

内容的提问来源于stack exchange,提问作者Yoandry Castellanos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:47:19