The ElementFlow custom control - can do CoverFlow too!
I am sure many of you have heard and even interacted with the CoverFlow view of iTunes. In the WPF world we have the good folks from Thirteen23, who have created an app called Harmony that shows off the use of CoverFlow. They make good use of the Viewport3D to pull the desired effect.
Recently I had the opportunity to develop a custom control similar to CoverFlow. I call this control the ElementFlow, because besides CoverFlow, the control can do lots of other views. In fact the whole view part of the control has been abstracted out so you can plug in your own view (if you wish). This is possible by creating a new ViewState and providing the necessary animations to flow the items.
Since the control is supposed to layout a list of items, it behaves very similar to an ItemsControl. However for various reasons I have not derived from ItemsControl (Why? - that’s a topic of a different blog post).
To demonstrate this control I have captured two videos, one which contains reflections and one without. In the first one I show only the CoverFlow control (with reflections ON). In the second video (reflections OFF) I start with the CoverFlow view and then switch my ViewStates. You can see that the view transition is very fluid and the selected-item is retained on different ViewStates. [Notethat not all layout-related dependency properties have mappings for different ViewStates.]
(Shows the Coverflow view with Reflections)
(Shows other ViewStates)
Some of the inner workings
- There are two ways in which you can add items to the ElementFlow control: creating the UIElement directly or by specifying a ElementsSource and ElementTemplate. Whenever an item is added, it is kept hidden separately and a VisualBrush of that item is texture-mapped onto the 3D Mesh. The mesh is then positioned according to its item-index in the list.
- I derive from a FrameworkElement instead of ItemsControl.
- To change the visual tree I override the following methods: GetVisualChild(), ArrangeOverride(), MeasureOverride() and the property: VisualChildrenCount
- Viewport3D is my only visual-child
What are the features of this control?
- Can do multiple forms of 3D list visualizations using ViewStates. Some of the out-of-box ViewStates include: CoverFlow, RollerCoaster, TimeMachine, Rolodex
- Pluggable ViewStates
- Fluid animations when switching between ViewStates
- Items can be added directly via XAML or in code using the Children property
- Supports data-binding via ElementsSource + ElementTemplate
- Detects changes to collection - Add/Remove/Update
- Various properties to control layout of items - ItemGap, FrontItemGap, PopoutDistance, TiltAngle. Changing these properties causes animated changes on the view.
- Mouse, Keyboard and Mousewheel interaction
- Virtualization of the view when dealing with a huge collection. Got to dig up those posts by Dan Crevier and Ben Constable :), think VirtualizingStackPanel and IScrollInfo !!
- I can’t release the Source code yet but keep visiting back :)