2015-06-25 76 views
0

我正在使用Windows 10通用应用程序,并在我的应用程序中使用ListView时看到一些闪烁的问题。我的ListView使用x:Bind绑定到View Model中的ObservableCollection。更新绑定集合时ListView闪烁

当用户执行某些操作或发生后台更新时,我会进行一些处理,需要刷新ObservableCollection。

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; 
     }); 
    } 

执行此代码后,ListView闪烁,然后滚动查看器一路走到顶部。有什么办法来防止这种情况,并让ListView的ScrollViewer停留在原来的偏移量?

回答

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); 
     } 

    } 
0

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

只需设置:

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

并拥有这火当然OnNotifyPropertyChanged。

+0

这样做的问题是它会导致ListView在UIItems集合更新后滚动到顶部。通过上述解决方案,滚动偏移量将保持不变。 –

+0

将ItemsUpdatingScrollMode设置为KeepScrollOffset:请参见:http://stackoverflow.com/questions/27924000/prevent-the-listview-from-scrolling-to-its-top-position-when-itemsource-changed/27933274#27933274 –

+0

但说实话:无论如何,当删除集合中的所有项目时,视图是否应该保留?如果您只是更换*一些*项目,为什么不更新这些而不是重新填充集合? –