ListView flickering when updating binding collection

时间:2015-06-25 18:32:33

标签: xaml listview win-universal-app

I am working on a Windows 10 Universal app and see some flickering issues when I use a ListView in my app. My ListView is using x:Bind to bind to an ObservableCollection in my View Model.

When user performs some actions, or a background update occurs, I do some processing that requires the ObservableCollection to be refreshed.

    private ObservableCollection<Item> UIItems = new ObservableCollection<Item>();
    private bool IsUpdating = false;

    private void UpdateUIProperties(List<Item> newItems)
    {
        DispatcherHelper.CheckBeginInvokeOnUI(() =>
        {
            IsUpdating = true;
            UIItems.Clear();
            foreach (var item in newItems)
            {
                if (item.IsVisible)
                {
                    UIItems.Add(item);
                }
            }
            IsUpdating = false;
        });
    }

After this code gets executed, the ListView flickers and then the Scrollviewer goes all the way to the top. Is there any way to prevent this and have the ListView's ScrollViewer stay at its original offset?

2 个答案:

答案 0 :(得分:1)

似乎对我有用的解决方案是将Itemsource绑定到Observable集合,然后让另一个集合包含要添加的项目。让集合中的Item实现下面的接口。如果要更新集合,请使用MergeCollection方法确保集合中的项目已保留,但它们具有新配置。

    public interface IConfigureFrom<T>
    {
        void ConfigureFrom(T other);
    }

    public static void MergeCollection<T>(ICollection<T> source, ICollection<T> dest)  where T : IConfigureFrom<T>, new()
    {
        // First remove entries at the bottom of the dest list that are no longer there
        if (dest.Count > source.Count)
        {
            for (int i = dest.Count - 1; i >= source.Count; i--)
            {
                var coll = dest as Collection<T>;
                if (coll != null)
                {
                    coll.RemoveAt(i);
                }
                else
                {
                    dest.Remove(dest.Last());
                }
            }
        }

        // reconfigure existing entries with the new configureation
        var sourecList = source.ToList();
        var destList = dest.ToList();

        for (int i = dest.Count - 1; i >= 0; i--)
        {
            var target = destList[i];
            var config = sourecList[i];
            target.ConfigureFrom(config);
        }


        // add new entries at the end and configure them from the source list
        for (int i = dest.Count; i < source.Count; i++)
        {
            T newItem = new T();
            newItem.ConfigureFrom(sourecList[i]);
            dest.Add(newItem);
        }

    }

答案 1 :(得分:0)

更改ListView中的所有项目时,通常最好只交换整个ItemsSource。

刚设置:

UIItems = new List<...>(your data); 

然后让它解雇OnNotifyPropertyChanged。