Pavan Podila, a WPF Disciple who’s blog has taught me much posted an ItemSkimmingPanel late last year that mimics the thumbnail skimming enhancements made to Mac IPhoto and IMovie. He describes it like so:
“Recently Apple released their next version of iLife, which has some cool enhancements to iPhoto and iMovie. One specific enhancement called “skimming” was interesting from my project’s perspective. The idea is that when you scrub your mouse over an album, it skims through all the photos in that album. The same interaction applies when you scrub your mouse over a movie clip: it skims through all of its frames.”
and provides this video showing his panel in action:
He accomplishes this by creating a custom panel, handling MouseDown, MouseUp and MouseMove events to achieve the scrubbing effect and manipulating the z-order of the images to pop them up to the top of the stack when visible.
If you’ve been following my previous posts you know I tend to want to delegate as much of the visual responsibility to XAML as much as possible in an attempt to keep the code behind a place for data fetching , construction and consumption. So naturally it tends to follow I’d be thinking about a XAML only solution to Item Skimming and today I present a potential solution.
The idea is simple. Using the concept conceived for the Rotoscope Animations post, we already have a way to skim through images in an enumerable list bound to a styled ListBox. In the Rotoscope Animation post, we bound the ListBox’s SelectedIndex to an Int32Animation and plowed right through the list displaying each item in order. In an Item Skimming control, we want the SelectedIndex to be bound to the captured mouse movement when a user drags horizontally across the image.
So, should we open up our code-behind and start writing event handlers for Mouse events - Up, Down, Capture? Heck no! Isn’t there already a WPF control allowing a user to drag their mouse and change a value?
The Slider Control to the Rescue
The Slider control allows a user to drag across the track and change the slider’s value in the process. We can bind this value to the SelectedIndex and this will scroll through the images in our data bound list.
Two obstacles with this approach:
- The Slider control is ugly.
- We don’t want the user to drag across a Slider, we want them to drag across the Image
My solutions to the obstacles?
- Make the Slider invisible - goodbye ugly.
- Make the invisible slider cover the image so it still responds to and handles drag events unbeknownst to the user
We can accomplish both solutions by manipulating the control template of the Slider. What does that look like? Well lucky for us, Microsoft provided an example customization right here.
I simply cut-n-pasted that bad boy into my file, changed the Trackbar background to Transparent, set all the borders to Transparent and changed the SliderThumb to be as high as it’s container with a width of 1 pixel.
Like so:
Now in our window, we simply add a Slider to the Grid binding it’s value to the ListBox’s SelectedIndex:
And the code-behind simply loads jpg images from the “Pets” directory in my MyPictures folder and sets it to the Window’s DataContext. Note: If you download the code you’ll need to change this directory name value to a directory of jpgs on your machine before running.
All that’s needed to be done is to wrap this solution in a UserControl and re-use where appropriate. In a future post I’ll try to add the skimming context control which you can see in the latter half of Pavan’s video.
The current result can be seen here: (video coming soon)
and the source is available here.
Enjoy!
May 28th, 2008 at 2:46 pm
Good Job ! You definitely have the WPF-talent to do interesting things. I have subscribed to your blog to learn more
May 28th, 2008 at 3:07 pm
Hi Pavan,
Thanks very much! I’ve aleady learned much from subscribing to yours.