Wednesday, October 23, 2013

Layout Cycle Detected - My story

If you are reading this then probably you hit one of the Silverlight errors I dread the most. Sometimes you see an error message, other times your screen just goes blank. Once I managed to intercept an exception in Visual Studio's debugger, but that was a very lucky shot.

There are a few links on the web that explain what is going on, and I followed this one on StackOverflow which proved to help me a lot. In my case I have a relatively complex Gantt chart -like user control that allows for zooming and scrolling. Individual Gantt items are also relatively complex user controls that need to be re-sized when the parent control is itself re-sized or when the user zooms in or out.

My initial implementation approach, which proved to be reliable on early tests, was to use the Gantt item child user control's SizeChanged event to re-size and re-position internal elements. As I said, this proved to work reliably with a limited number of items. When I started to test the main control with real live data, the problem emerged.

The fault was on the design itself - you should never change the size of your user control inside the user control's SizeChanged event. Never. This will trigger a recursion loop that the layout engine may never recover from and you will get the dreaded exception, or blank screen.

My solution was very simple - I moved all of the code from the event handler to a public method that is called from the parent control's code. This works well because there is no other instance that re-sizes the child control but its parent, so there is only one entry point for calling the code. Instead of assigning a value to the children's Width property, now the parent user control code calls a SetWidth method on the child that besides setting the width, also executes the re-sizing logic outside the SizeChanged event handler. Voilá.