【发布时间】:2014-01-26 14:11:17
【问题描述】:
我正在使用ListView 控件来显示一些数据行。有一个后台任务接收对列表内容的外部更新。新收到的数据可能包含更少、更多或相同数量的项目,而且项目本身也可能发生了变化。
ListView.ItemsSource 绑定到 OberservableCollection (_itemList),因此对 _itemList 的更改也应该在 ListView 中可见。
_itemList = new ObservableCollection<PmemCombItem>();
_itemList.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
L_PmemCombList.ItemsSource = _itemList;
为了避免刷新完整的 ListView,我将新检索到的列表与当前的 _itemList 进行了简单的比较,更改不相同的项目并在必要时添加/删除项目。集合“newList”包含新创建的对象,因此替换 _itemList 中的项目会正确发送“刷新”通知(我可以使用 ObservableCollection 的事件处理程序OnCollectionChanged 记录该通知)
Action action = () =>
{
for (int i = 0; i < newList.Count; i++)
{
// item exists in old list -> replace if changed
if (i < _itemList.Count)
{
if (!_itemList[i].SameDataAs(newList[i]))
_itemList[i] = newList[i];
}
// new list contains more items -> add items
else
_itemList.Add(newList[i]);
}
// new list contains less items -> remove items
for (int i = _itemList.Count - 1; i >= newList.Count; i--)
_itemList.RemoveAt(i);
};
Dispatcher.BeginInvoke(DispatcherPriority.Background, action);
我的问题是,如果在此循环中更改了许多项目,ListView 不会刷新并且屏幕上的数据保持原样......我不明白。
即使是这样的简单版本(交换所有元素)
List<PmemCombItem> newList = new List<PmemCombItem>();
foreach (PmemViewItem comb in combList)
newList.Add(new PmemCombItem(comb));
if (_itemList.Count == newList.Count)
for (int i = 0; i < newList.Count; i++)
_itemList[i] = newList[i];
else
{
_itemList.Clear();
foreach (PmemCombItem item in newList)
_itemList.Add(item);
}
工作不正常
这有什么线索吗?
更新
如果我在更新所有元素后手动调用以下代码,一切正常
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
但这当然会导致 UI 更新我仍然想避免的所有内容。
【问题讨论】:
-
您是否尝试过同步
Dispatcher.Invoke而不是异步Dispatcher.BeginInvoke? -
我使用 Dispatcher.Invoke 得到了相同的结果
-
我们在这里谈论多少项目?您是否尝试过不同的调度程序优先级?
-
该列表有大约 100 个项目并且在不断变化,例如其中4个工作正常,更改10个没有视觉效果。我尝试了几个优先事项,到目前为止没有改变行为
-
为了确保您的更新代码没有任何问题,如果您简单地清除整个
_itemList然后添加来自newList的所有项目,它的行为如何?