Click here to Skip to main content
15,897,891 members
Articles / Desktop Programming / WPF

Rotating WPF Content in 3D Space

Rate me:
Please Sign up or sign in to vote.
4.92/5 (72 votes)
22 Mar 2009CPOL9 min read 338.5K   13.8K   170  
Introducing ContentControl3D: a control that makes it easy to incorporate 3D flips into any WPF user interface.
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml;
using Thriple.Controls;
using Thriple.Panels;

namespace WpfDisciplesBlogRoll3D
{
	public partial class BlogRollWindow : Window
	{
		Panel3D _panel3D;
		readonly TimeSpan ANIMATION_LENGTH = TimeSpan.FromSeconds(.7);

		public BlogRollWindow()
		{
			InitializeComponent();

			this.listBox.PreviewKeyDown += new KeyEventHandler(listBox_PreviewKeyDown);
		}

		void listBox_PreviewKeyDown(object sender, KeyEventArgs e)
		{
			// This is necessary to workaround a bug in WPF that arises
			// when you press the Tab key when keyboard focus is in the
			// ScrollViewer.  This bug does not arise under normal circumstances.
			e.Handled = e.Key == Key.Tab;
		}

		void OnPanel3DLoaded(object sender, RoutedEventArgs e)
		{
			// Grab a reference to the Panel3D when it loads.
			_panel3D = sender as Panel3D;
		}

		void Open_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = true;
		}

		void Open_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			// The ApplicationCommands.Open command is used for a variety of purposes here.
			// It's a dirty hack, but who cares...this is just a demo.

			var elem = e.OriginalSource as FrameworkElement;
			int childIndex = this.listBox.Items.IndexOf(elem.DataContext);
			int visibleIndex = _panel3D.GetVisibleIndexFromChildIndex(childIndex);
			if (0 < visibleIndex)
			{
				// The user clicked on an item that was not in the front of the scene,
				// so tell the Panel3D to animate it to the front.
				if (!_panel3D.IsMovingItems)
					this.MoveItems(visibleIndex, true);
			}
			else
			{
				XmlAttribute attr = e.Parameter as XmlAttribute;
				if (attr != null)
				{
					// The user clicked on the button that opens up a blog.
					string url = attr.Value;
					if (!String.IsNullOrEmpty(url))
						Process.Start(url);
				}
				else
				{
					// The user clicked on a blogger's image, so rotate the item.
					ContentControl3D.RotateCommand.Execute(null, elem);
				}
			}
		}

		void OnListBoxItemUnselected(object sender, RoutedEventArgs e)
		{
			// When the user brings a new ListBoxItem to the front of the 3D scene
			// it becomes the selected item in the ListBox.  At that time, we must
			// verify that the previously selected item's front side is facing forward.
			DependencyObject depObj = e.OriginalSource as DependencyObject;
			while (depObj != null)
			{
				if (VisualTreeHelper.GetChildrenCount(depObj) == 0)
					break;

				depObj = VisualTreeHelper.GetChild(depObj, 0);
				ContentControl3D cc3D = depObj as ContentControl3D;
				if (cc3D != null)
				{
					cc3D.BringFrontSideIntoView();
					break;
				}
			}
		}

		void MoveForwardButtonClicked(object sender, RoutedEventArgs e)
		{
			this.MoveItems(1, true);
		}

		void MoveBackButtonClicked(object sender, RoutedEventArgs e)
		{
			this.MoveItems(1, false);
		}

		void PageForwardButtonClicked(object sender, RoutedEventArgs e)
		{
			this.MoveItems(3, true);
		}

		void PageBackButtonClicked(object sender, RoutedEventArgs e)
		{
			this.MoveItems(3, false);
		}

		void MoveItems(int itemCount, bool forward)
		{
			_panel3D.MoveItems(itemCount, forward, ANIMATION_LENGTH);
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Josh creates software, for iOS and Windows.

He works at Black Pixel as a Senior Developer.

Read his iOS Programming for .NET Developers[^] book to learn how to write iPhone and iPad apps by leveraging your existing .NET skills.

Use his Master WPF[^] app on your iPhone to sharpen your WPF skills on the go.

Check out his Advanced MVVM[^] book.

Visit his WPF blog[^] or stop by his iOS blog[^].

See his website Josh Smith Digital[^].

Comments and Discussions