views:

509

answers:

1

I've been adding a bit of animation to my WPF application.

Thanks to Dan Crevier's unique solution to animating the children of a panel combined with the awesome WPF Penner animations it turned out to be fairly straightforward to make one of my controls look great and have its children move about with some nice animation.

Unfortunately this all comes with a performance overhead. I'm happy to have the performance hit when items are added/removed or the control is resized, but it seems that this perf hit occurs consistently throughout the application's lifetime, even when items are completely static.

The PanelLayoutAnimator class uses an attached property to hook the UIElement.LayoutUpdated event. When this event fires, render transforms are animated to cause the children to glide to their new positions.

Unfortunately it seems that the LayoutUpdated event fires every second or so, even when nothing is happening in the application (at least I don't think my code's doing anything -- the app doesn't have focus and the mouse is steady.) As the reason for the event is not immediately apparent to the event handler, all children of the control have to be reevaluated. This event is being called about once a second when idle. The frequency increases when actually using the app.

So my question is, how can I improve the performance here? Any answer that assists would be appreciated, but I'm currently stuck on these sub-questions:

  1. What causes the LayoutUpdated event to fire so frequently? Is this supposed to happen, and if not, how can I find out why it's firing and curtail it?

  2. Is there a more convenient way within the handler to know whether something has happened that might have moved children? If so, I could bail out early and avoid the overhead of looping each child.

For now I will work around this issue by disabling animation when there are more than N children in the panel.

A: 

I have the same problem, LayoutUpdated is firing up like crazy. The not so good workaround I found was to register the event when needed, perform the work and de-register the event in the event handler. Still looking for the cause of the problem to resolve it at the source.