为了更好的理解ObservableCollection是如何自动刷新UI的,下面贴一些ObservableCollection的代码:
protected override void SetItem(int index, T item)
{
this.CheckReentrancy();
T oldItem = base[index];
base.SetItem(index, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem, index));
}
{
this.CheckReentrancy();
T oldItem = base[index];
base.SetItem(index, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, oldItem, index));
}
原因就在于上面调用了this.OnCollectionChanged方法,为什么一般的list不会有这样的跨线程为题,原因也在这,因为刷新UI不应该是UI线程的工作,超出了自己的范围。我写过代码,如果不和UI绑定,它本身是可以支持跨线程的,只是UI线程的东西,不是那么容易的可以动的。
基于上面的相发,我想重写
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (this.CollectionChanged != null)
{
this._busy = true;
try
{
this.CollectionChanged(this, e);
}
finally
{
this._busy = false;
}
}
}
{
if (this.CollectionChanged != null)
{
this._busy = true;
try
{
this.CollectionChanged(this, e);
}
finally
{
this._busy = false;
}
}
}
下面是我重写的方法,很简单但很实用:
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
try
{
if (curerntDispatcher != null)
{
curerntDispatcher.BeginInvoke(() =>
{
base.OnCollectionChanged(e);
});
}
else
{
base.OnCollectionChanged(e);
}
}
catch (Exception exce)
{
Utils.e(exce.Message, exce);
}
}
{
try
{
if (curerntDispatcher != null)
{
curerntDispatcher.BeginInvoke(() =>
{
base.OnCollectionChanged(e);
});
}
else
{
base.OnCollectionChanged(e);
}
}
catch (Exception exce)
{
Utils.e(exce.Message, exce);
}
}
这样,我们就不必为我们所用到的每个方法都重写了,也就是说上一篇的Add, Remove,等方法都不需要我们自己重写了。