Frame-based animation in WPF
I recently was working on the ubiquitous photo/slideshow app in WPF. This is something I've been tinkering with off and on for last 6 months. The original intention was to create a photo slideshow application for my upcoming wedding. Being the nerd, a static video slideshow just wasn't going to cut it.
Along the way I learned quite a bit about keeping performance up and memory usage low while working with tons of images. It's finally in a position where it's almost done and I wanted to add a few tweaks. The photos zoom in and randomly arrange like they were dropped on a table. Once there, they show one by one.
I wanted to add a little random "drift" while the image was showing to make it more interesting to the eye. I started originally by creating random storyboards and listening to the Storyboard.Completed event. When the event fired I created a new storyboard to animate my photo's Canvas.Left and Top properties. This worked, but there was an annoying lag between the stop and start of the animations.
I wanted to move to a frame-based animation rather than WPF's built-in time-based animation style. I could have used a timer to update my properties, but I wanted to work more within the constraints of WPF. I found articles for Silverlight that indicate an empty storyboard with no duration will fire it's completed event on the next frame, there you can update your properties and restart the storyboard to update your properties every frame. Although this may work in Silverlight, I could not get it to work in WPF. Though as I look back, I didn't try setting the Duration to "0:0:0". I wonder if that would work?
Regardless, the technique I ended up using was listening to CompositionTarget.Rendering event it code-behind. The event fires before your UI renders each frame, allowing you to hook in and do frame based animation.
For more information, you can go here:
WPF ListBox Virtualization
Virtualization in WPF is amazing when you get it, annoying when you lose it. I'm working on a form where the user can dynamically filter and sort a ListBox. I'm using a DataTemplate to give a nice card-like view to each object, which makes it take up a lot of space on the screen. To fix this I used the WrapPanel as the ListBox's ItemsPanel.
WrapPanel is not virtualized, I can't find one that is and don't have any time to write one myself. So I came up with a work around to give the user a fixed number of column view using the standard panel for a ListBox. This got me virtualization back. Then I wanted to smoothly scroll so I turned ScrollViewer.CanContentScroll to false. Smooth scrolling, no virtualization. Because this box may have thousands of records in it, performance is much more important than smooth scrolling.
The moral of the story is, if you're working on something in WPF and performance is important and you might have a large dataset coming in. Double check your changes to controls to make sure you're maintaining virtualization. If anybody has a good list of what disables virtualization (grouping, custom panels, smooth scrolling), I'd like to see it.