更新绑定集合时 ListView 闪烁
ListView flickering when updating binding collection
我正在开发 Windows 10 通用应用程序,当我在我的应用程序中使用 ListView 时发现一些闪烁问题。我的 ListView 使用 x:Bind 绑定到我的视图模型中的 ObservableCollection。
当用户执行某些操作或发生后台更新时,我会执行一些需要刷新 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开始闪烁,然后Scrollviewer一直到最上面。有什么方法可以防止这种情况发生并使 ListView 的 ScrollViewer 保持在其原始偏移量?
一个似乎对我有用的解决方案是将 Itemsource 绑定到一个 Observable 集合,然后让另一个集合包含您要添加的项目。让集合中的项目实现下面的接口。当您想要更新集合时,请使用 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);
}
}
更改 ListView 中的所有项目时,通常最好只交换整个 ItemsSource。
刚刚设置:
UIItems = new List<...>(your data);
当然,让它触发 OnNotifyPropertyChanged。
我正在开发 Windows 10 通用应用程序,当我在我的应用程序中使用 ListView 时发现一些闪烁问题。我的 ListView 使用 x:Bind 绑定到我的视图模型中的 ObservableCollection。
当用户执行某些操作或发生后台更新时,我会执行一些需要刷新 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开始闪烁,然后Scrollviewer一直到最上面。有什么方法可以防止这种情况发生并使 ListView 的 ScrollViewer 保持在其原始偏移量?
一个似乎对我有用的解决方案是将 Itemsource 绑定到一个 Observable 集合,然后让另一个集合包含您要添加的项目。让集合中的项目实现下面的接口。当您想要更新集合时,请使用 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);
}
}
更改 ListView 中的所有项目时,通常最好只交换整个 ItemsSource。
刚刚设置:
UIItems = new List<...>(your data);
当然,让它触发 OnNotifyPropertyChanged。