I have a WPF app that draws a compass. There is a large ring with tick marks and labels. I have a checkbox that toggles the compass graphics on and off. When I first start up the app, the compass turns on and off instantly.
Meanwhile, I have a combo box that grabs some data from a local database and uses that to render some overlay graphics. After using this combo box, the compass graphics no longer toggle quickly. In fact, the UI completely freezes for about 4 seconds whenever I click the checkbox.
I attempted to profile my app using Window Performance Profiling Tool for WPF. When I activated the checkbox, not only did my app freeze, so did the profiler. The graphs “catched up” afterward, but this tells me something must be seriously wrong.
I’ve managed to nail down that the problem graphics are the tick marks (not the numeric labels). If I eliminate them, the freezing problem stops. If I cut them down from 360 to, say, 36, the app still freezes, but for less time. Again, no matter how many tick marks I have, they toggle instantly when the app first starts.
My question is, How do I figure out why the toggle for my compass graphics goes from instant to horribly slow? I’ve tried extensive profiling and debugging, and I just can’t come up with any reason why setting the Visibility on some tick marks should ever cause the app to freeze.
Edit
Okay, I’ve stripped everything out of my app to just the bare essentials, zipped it up, and uploaded it to Sendspace. Here is the link (it’s about 143K):
http://www.sendspace.com/file/n1u3yg
[Note: don’t accidentally click the banner ad, the real download link is much smaller and lower on the page.]
Two requests:
-
Do you experience the problem on your machine? Try opening Compass.exe (in bin\Release) and clicking the check box rapidly. The compass tick marks should turn on and off with no delay. Then, select an item from the combo box and try rapidly clicking the check box again. On my machine, it’s very laggy, and after I stop rapid-fire clicking, it takes a few seconds for the graphics to catch up.
-
If you do experience the lag, do you see anything in the code that could be causing this odd behavior? The combo box is not connected to anything, so why should selecting an item from it affect the future performance of other graphics on the window?
Although ANTS didn’t indicate a particular performance ‘hotspot’, I think that your technique is slightly flawed as it seems that every tick has a
ViewModelthat is responsible for handling an individual tick, and you are individually binding those ticks to the view. You end up creating 720 view models for these ticks that fire the a similar event each time the entire compass is shown or hidden. You also create a new LineGeometry every time this field is accessed.The recommended approach for WPF in a custom drawn situation like this is to use a
DrawingVisualand embrace the retained mode aspect of WPF’s rendering system. There are several googleable resources that talk about this technique, but the gist is to declare a compass class inherits fromFrameworkElement, and some smaller classes that inherit fromDrawingVisualand use that to render the compass. With this technique, you can still have a ViewModel drive the compass behavior, but you wouldn’t have individual viewmodels for each part of the compass. I’d be inclined to decompose the compass into parts such as bezel, arrow, sight, etc… but your problem may require a different approach.