The tale of the list control, the async call and the layout cycle error
This one had me banging my head against the wall for a long time, refreshing a list of items was causing the app to crash when it was repopulated.
Disclaimer: I see my solution as no more than a hack, but a necessary one.
Setting the scene
I had an ObservableCollection
of user actions that were populated when the user tapped on the item in another list. A bit like a master detail approach I guess. The items displayed would vary and the list could be cleared and repopulated. Further to that the items came from multiple async
requests to an external service that could come back at different times in different orders. Hence the need for an ObservableCollection
.
Populating the list the first time was not a problem, however repopulating that list would crash the app with this error:
Layout cycle detected. Layout could not complete.
My exact steps were:
- Populating the list with three separate
async
requests - Clearing the list of items
- Doing step 1 again
Understanding the error
I won't claim to fully understand it, but from what I learnt (Googled), a layout cycle error is a UI error where the layout is unable to complete because there is an infinite loop. This can be caused by a control handling event changes such as size that just get stuck by continually firing. This stack overflow answer has some more detail.
Narrowing it down
I was pretty sure it was the control I was using to display the items that was causing the problem. I was using ItemsControl
. Changing to ListBox
or ListView
made no difference.
Finding the cause
After a lot of hair pulling and general cursing this comment in a Xaramin forum gave me a clue to what was causing it. Async calls.
To retrieve user action three async
calls were being made each updating the ObservableCollection
with items. I took two of the calls out so the list was only being repopulated once, the error stopped.
If this is the cause of your problem and you can re-engineer your solution to a single or synchronous request I would recommend that. Unfortunately I was able to do neither.
The hack
I had seen several suggestions that setting the size of the control would help with this error, as the layout was fixed and could be calculated. I had given up on finding a solution that seemed sensible to me so decided to give this a go. I could not set a fixed height as the list could vary in size. Instead I set a MinHeight
value to the height of one row. And it worked! Giving it a starting point was enough to stop the layout cycle error occurring and I could get on with my life.