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在异步请求后,逐条将数据渲染显示,这样给用户的体验就好多了;

代码 :

 ObservableCollection<Friend> items = new ObservableCollection<Friend>();
            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);


                });
 }  


 
 
posted @ 2012-02-20 16:41  J默  阅读(1410)  评论(1编辑  收藏  举报