window phone7中listbox,ItemsControl等项渲染速度慢的解决方案
背景:ui使用ScrollViewer+ItemsControl(Listbox是有这两个控件组合出来的),绑定到ItemsControl上的ItemSource的是一个ObservableCollection<T>,使用它是因为它实现了INotifyCollectionChanged, INotifyPropertyChanged接口,在其它地方修改这个ObservableCollection<T>集合,就会更新对应ui显示,我说的其它地方当然指的有codebehind里,还有使用的mvvm框架里的viewModel等,本人使用的是mvvm框架;在viewmodel里异步请求数据,获取完数据后添加到ObservableCollection<T>集合里就可以了,这种实现,功能上ok,可是伴随的问题来了,当viewModel初始化后发送异步请求,在添加到ObservableCollection<T>过程中,Ui并未逐条数据渲染显示,而是等一段时间后渲染显示,这个当数据量达到40-60条时,渲染特别慢,这当然是不能忍受的;
分析:初步分析是因为性能、集合太大等引起的,但是在调试这些之后并没能解决问题;找了好多方法,未能解决;后来看了msdn上的博客才知道具体解决办法,
大致原因是因为,我获取数据的请求时异步请求,在获取到数据后,异步add数据到到ObservableCollection<T>占用了主线程,一直等到将所有数据添加到ObservableCollection<T>后,主线程才回到ui线程将ObservableCollection<T>的Change更新显示到UI上;
解决办法: 了解这个之后,就可以找到解决办法了,就是在foreach将response里的数据添加到ObservableCollection<T>过程中,让单签线程暂停30毫秒,这时候逐次调用ui跨线程更新方法,在这个时间里,ui线程有足够资源去更新ui显示,最终效果就是listbox或ItemsControl在异步请求后,逐条将数据渲染显示,这样给用户的体验就好多了;
代码 :
int sleepcounter = 2;
int itemcounter = 0;
foreach (ItemViewModel item in items)
{
itemcounter++;
if (itemcounter % sleepcounter == 0)
{
System.Threading.Thread.Sleep(20);
}
//add a dummy item
var myItem = item;
// copy the data over
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
// copy the list of bingimages over
this.items.Add(myItem);
});