我有一个问题,这很无聊,我花了很多时间以最好的方式解决我的问题。
问题:我有两个ObservableCollections。 (OCAux - Auxiliar OC,OCMain - 主要OC Binded UI)
我已经请求了http,5个请求。对于每个对请求的响应都会添加到项目OCAux中,然后对项目进行排序。在将此项添加到订购到我的OCMain的每个项目之后,这会自动通知UI(具有约束力)。问题是,当添加一个新项目时,这不是有序的,因为我的订单是OCAux的结果,即只有订单请求。如果您在将项目添加到OCMain后订购该项目,它会闪烁。 我可以在每次添加项目时订购OCMain,但在添加项目时会导致UI闪烁。
这被规避如下,但UI中仍然存在这些“闪烁”:
foreach (var item in OCMain)
{
OCAux.Add(item);
}
ObservableCollection<Movies> moviesSortedByDatetime= new ObservableCollection<Movies>
(OCAux.OrderByDescending(item=> item.DateTime));
OCMain.Clear();
foreach (var item in moviesSortedByDatetime)
{
if (!OCMain.Contains(item))
{
OCMain.Add(item);
}
}
任何人都知道如何将项目插入ObservableCollection的正确位置?
提前致谢
答案 0 :(得分:0)
对于批量插入,可以为每次更改不断更新UI(除非您需要实时更新)。除非您有充分的理由保留OCAux
,否则我会OCMain
使用自定义IObservableCollection
实施的有序集合,以便在批量完成后推迟通知。它可以通过两种方式完成:
1)最简单的方法是添加BeginUpdate()
方法来禁用通知。使用该集合完成作业后,您可以使用EndUpdate()
重新启用通知。继承自ObservableCollection<T>
的类的概念证明:
public void BeginUpdate() {
_disableNotifications = true;
}
public void EndUpdate() {
_disableNotifications = false;
if (_changed) {
OnCollectionChanged(
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
_changed = false;
}
}
protected override OnCollectionChanged(NotifyCollectionChangedEventArgs e) {
if (_disableNotifications)
_changed = true;
else
base.OnCollectionChanged(e);
}
对INotifyPropertyChanged
和PropertyChanged
属性的Count
界面提升事件Items
也应用相同的逻辑。
2)第二个选项稍微复杂一点,但即使您不知道批量操作何时开始和结束,它仍然有效。首先,让我们做一个假设:用户不会注意到更新是否会延迟100毫秒。在这种情况下,我们可以做的是忽略更改,并在NotifyCollectionChangedAction.Reset
毫秒后发送一个NotificationDelay
。拥有多少更新并不重要,只有一个会在第一个更新NotificationDelay
毫秒后发送。概念证明:
protected override OnCollectionChanged(NotifyCollectionChangedEventArgs e) {
// Another event already queued a delayed notification
if (_isTimerRunning)
return;
// Assuming _timer is a System.Timers.Timer object already configured
// and OnTimerElapsed method attached to its Elapsed event. Note that
// you may also use System.Threading.Timer, pick the proper one
// according to MSDN and your requirements
_isTimerRunning = true;
_timer.Start();
}
private void OnTimerElapsed(Object source, ElapsedEventArgs e) {
_isTimerRunning = false;
_timer.Stop();
base.OnCollectionChanged(
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
同样,您必须为INotifyPropertyChanged
实施做类似的事情。
请注意,在这两种情况下,我们都会删除一些信息,因为CollectionChanged
不会触发,例如,使用NotifyCollectionChangedAction.Add
,但仅限NotifyCollectionChangedAction.Reset
。无论如何,如果它仅用于绑定,那么您对INotifyPropertyChanged
通知更感兴趣,这应该不是问题。