0

I have a Pivot Page with four pivots. In two of the pivots I have a ListBox which I fill with information in the form of a grid. I Bind the ListItems to an ObservableCollection which is filled with information fetched asynchronous from a WCF.

However, the UI seems to freeze when the DataContext is set and the UI is filling the ListBox with data. The more ListItems, the longer it freezes.

Edit: Calrification. I can still scroll the page up/down, but I can't swipe to navigate to a different pivot. The transition happens after the UI unfreezes.

Is there any way to fill the ListBox without freezing the UI?

Edit: Some sample code loosely explaining what happens.

The listbox

<ListBox Name="lbInterruptYesterday" ScrollViewer.VerticalScrollBarVisibility="Disabled"
    ItemsSource="{Binding Interrupts}" 
    ItemTemplate="{StaticResource InterruptListItem}" Tap="Interrupt_OnTap">
</ListBox>

Interrupts is an ObservableCollection containing Interrupt objects.

InterruptListItem contains a grid with TextBlocks, the text is Binding to variables in an Interrupt-object.

I fetch the data with an asynchronous call to a WCF. When completed I do:

(sender, e) => Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        //Some code handling the result which I put in the ObservableCollection
        Production.Interrupts.add(new Interrupt());
        //Set the DataContext    
        DataContext = Production;
    });

And when the DataContext is set, the UI freezes until it is updated.

Naning
  • 734
  • 2
  • 8
  • 18

1 Answers1

0

This may be because of ObservableCollection is firing an event causing UI to update on every item you add there. If you add lots of items, it can be time-consuming. The solution is to create a more clever ObservableCollection, which you can pause and resume, in terms of event firing. Here's an example which you could try and see if it helps.

Community
  • 1
  • 1
Haspemulator
  • 11,050
  • 9
  • 49
  • 76
  • No. The problem seems to remain, even if I only trigger the event once. I have to clarify though. I seem to be able to scroll the page up/down, but I can't swipe to navigate to a different pivot. I updated the question. – Naning Feb 18 '13 at 14:28
  • Then I guess it's time to do some profiling: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj215908%28v=vs.105%29.aspx – Haspemulator Feb 18 '13 at 14:36
  • Which basically tells me everything I already know. High CPU usage from the UI followed by "UI Stuttering". And I can't successfully analyze anywhere where I can optimize. The UI seems to draw the full listbox at once, which takes too long. It would solve my problem if I could make it only draw the new items when I add something, instead of the full listbox. – Naning Feb 19 '13 at 09:35
  • How many items do you have in your ListBox? Another option would be to use LongListSelector control (if you're on WP7 than you'll need Windows Phone Toolkit from Microsoft). It supports items virtualization, i.e. only loads items into the view when necessary. – Haspemulator Feb 19 '13 at 10:46
  • Between 0 and 30ish. It varies. The problem isn't really the number of items, it's the amount of information each item contains. Each item is a grid of 10 rows and 4 columns. Each cell in the grid contains 1 or 2 textblocks for a total of 24 textblocks. Some collapsed(17 to begin with), some visible(7 to begin with). Provided the system is clever enough to not draw collapsed items, the UI still often has to draw 100-200 text blocks at once which causes it to freeze. – Naning Feb 19 '13 at 11:24
  • Wow, your ItemTemplate looks quite complicated. Grid is very calculation-heavy panel, AFAIK. I would try to get rid of the Grid in your ItemTemplate (just for testing purposes) and see if it will improve the situation. Just change it to StackPanel, for example, or even better to Canvas, and see if performance improves. And I would also try to change ListBox to LongListSelector, as a next attempt. – Haspemulator Feb 19 '13 at 12:43
  • It's not complicated. Just... Big. Changing the ItemTemplate into a canvas obviously speeds up the drawing, and everything works smoothly. Changing the ListBox into a LongListSelector doesn't change anything. What probably would help is to have the UI draw the new item every time an item is added to the ObservableCollection. Right now, it waits until the Dispatcher thread is done filling it before drawing. – Naning Feb 19 '13 at 13:10
  • 1
    If changing to Canvas fixes things, I guess you're hitting the architectural limitation of Windows Phone and the Grid panel particularly. I could only suggest simplifying your ItemTemplate somehow. There's no way to draw controls outside of Dispatcher (UI thread) on Windows Phone. – Haspemulator Feb 19 '13 at 14:04
  • I found a workaround. Kind of. Using a BackgroundWorker to add the items and Thread.Sleep between adding. The UI will respond during the sleeping time. It's not perfect, but it beats waiting. http://stackoverflow.com/questions/11412403/how-to-create-a-fast-loading-wrapping-listbox – Naning Feb 19 '13 at 14:18
  • Okay, glad you've found a workaround, but anyway I'd strongly suggest you to simplify your layout. Most probably there are ways to achieve what you want with simpler means, like combination of StackPanels with different orientation. It will be much faster than Grid. You're just creating unnecessary strain on the CPU, lowering battery life, introducing non-deterministic behavior by applying that workaround. – Haspemulator Feb 19 '13 at 15:22