Click here to Skip to main content
15,896,207 members
Articles / Programming Languages / C#

Silverlight Carousel: Creating a Silverlight Control Displays Picture in an Interactive Carousel

Rate me:
Please Sign up or sign in to vote.
4.89/5 (58 votes)
2 Aug 2009Ms-PL4 min read 708.2K   6.1K   131  
This article describes how to create and use the Silverlight Carousel control.
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Media.Imaging;

namespace Cokkiy.Display
{
    /// <summary>
    /// A control display it's items like a carsouel.
    /// </summary>
    [TemplatePart(Name = Carousel.ElementSelectedItemViewerName, Type = typeof(ItemViewerControl))]
    [TemplatePart(Name=Carousel.ElementCarouselCanvas,Type=typeof(Canvas))]
    [TemplatePart(Name=Carousel.ElementFullScreenButtonName,Type=typeof(Button))]
    public class Carousel : Control
    {
        /// <summary>
        /// The resources dictionary key of the carousel storyboard.
        /// </summary>
        private const string CarouselStoryboardKey = "carouselStoryboard";

        /// <summary>
        /// Represents the circumference of a circle, specified by the constant, π. 
        /// </summary>
        private const double _2PI = 2 * Math.PI;

        /// <summary>
        /// The root visual size
        /// </summary>
        private Size rootVisualSize;

       
        #region Template Parts

        /// <summary>
        /// The name of the selected item panel element
        /// </summary>
        private const string ElementSelectedItemViewerName = "selectedItemViewer";
        /// <summary>
        ///  The name of the carsouel canvas element
        /// </summary>
        private const string ElementCarouselCanvas = "carouselCanvas";

        /// <summary>
        /// The name of the fullscreen button element
        /// </summary>
        private const string ElementFullScreenButtonName = "fullScreenButton";

        /// <summary>
        /// The panel used to display the selected item's larger image (or visual)
        /// </summary>
        private ItemViewerControl _selectedItemViewer;

        /// <summary>
        /// The canvas used to display carsouel like control
        /// </summary>
        private Canvas _carouselCanvas;

        /// <summary>
        /// The full screen button
        /// </summary>
        private Button _fullScreentButton;

        /// <summary>
        /// Gets or sets the SelectedItemPanel template part.
        /// </summary>
        private ItemViewerControl SelectedItemViewer
        {
            get
            {
                return _selectedItemViewer;
            }
            set
            {
                if (_selectedItemViewer != null)
                {
                    // Detach the MouseLeftButtonUp event handler
                    _selectedItemViewer.MouseLeftButtonUp -= _selectedItemViewer_MouseLeftButtonUp;
                }
                _selectedItemViewer = value;

                if (_selectedItemViewer != null)
                {
                    // Attach the MouseLeftButtonUp event hander
                    _selectedItemViewer.MouseLeftButtonUp += new MouseButtonEventHandler(_selectedItemViewer_MouseLeftButtonUp);
                }
            }
        }

        /// <summary>
        /// Gets or sets the CarouselCanvas template part.
        /// </summary>
        private Canvas CarouselCanvas
        {
            get
            {
                return _carouselCanvas;
            }
            set
            {
                if (_carouselCanvas != null)
                {
                    // detach the event handler
                    _carouselCanvas.SizeChanged -= _carouselCanvas_SizeChanged;
                }
                _carouselCanvas = value;

                if (_carouselCanvas != null)
                {
                    // attach the event handler
                    _carouselCanvas.SizeChanged += new SizeChangedEventHandler(_carouselCanvas_SizeChanged);

                    // Set the background
                    _carouselCanvas.Background = CarouselBackground;
                }
            }
        }

        /// <summary>
        /// Gets or sets the full screen button template part.
        /// </summary>
        private Button FullScreenButton
        {
            get
            {
                return _fullScreentButton;
            }
            set
            {
                if (_fullScreentButton != null)
                {
                    // detach the event handle
                    _fullScreentButton.Click -= _fullScreentButton_Click;
                    Application.Current.Host.Content.FullScreenChanged -= Content_FullScreenChanged;

                }

                _fullScreentButton = value;

                if (_fullScreentButton != null)
                {
                    _fullScreentButton.Click += new RoutedEventHandler(_fullScreentButton_Click);
                    //Attach a event handle for full screen
                    Application.Current.Host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
                }
            }
        }

        #endregion               

        
        #region AutoTurn property

        /// <summary>
        /// Gets or sets a value indicating the carousel will be auto turn or not.
        /// </summary>
        /// <value> A value indicating the carousel will be auto turn or not.
        /// <para> The default value is true, which indicating the carousel will be auto turn when 
        /// it crated.</para></value>
        public bool AutoTurn
        {
            get { return (bool)GetValue(AutoTurnProperty); }
            set { SetValue(AutoTurnProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AutoTurn.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="AutoTurn"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty AutoTurnProperty =
            DependencyProperty.Register("AutoTurn", typeof(bool), typeof(Carousel), new PropertyMetadata(true, OnAutoTurnPropertyChanged));

        /// <summary>
        /// <see cref="AutoTurn"/> PropertyChangedCallback static function.
        /// </summary>
        /// <param name="d"><see cref="Carousel"/> control whose <see cref="AutoTurn"/> property is changed.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs which contains the old and new values.</param>
        private static void OnAutoTurnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Carousel carousel = d as Carousel;
            carousel.AutoTurnChanged((bool)e.NewValue);
        }
        
        #endregion


        #region TurnDirection Property
        /// <summary>
        /// Gets or sets a value indicating the carouse turnning direction.
        /// </summary>
        /// <value>A value indicating the carousel turnning in clockwise 
        /// or in counterclockwise.
        /// <para>The default value is Clockwise.</para></value>
        public TurnDirection TurnDirection
        {
            get { return (TurnDirection)GetValue(TurnDirectionProperty); }
            set { SetValue(TurnDirectionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TurnDirection.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="TurnDirection"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty TurnDirectionProperty =
            DependencyProperty.Register("TurnDirection", typeof(TurnDirection),
            typeof(Carousel),
            new PropertyMetadata(TurnDirection.Clockwise, OnTurnDirectionPropertyChanged));

        /// <summary>
        /// The <see cref="TurnDirection"/> PropertyChangedCallback function.
        /// </summary>
        /// <param name="d">The <see cref="Carousel"/> control whose <see cref="TurnDirection"/> property changed.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs which contains the old and new values.</param>
        private static void OnTurnDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Carousel carousel = d as Carousel;
            carousel.TurnDirectionChanged((TurnDirection)e.NewValue);
        } 
        #endregion


        #region Duration Property
        /// <summary>
        /// Gets or set a timespan value specify the carousel turns one lap spended.
        /// </summary>
        /// <value>A timespan value spending which the carousel turns one lap.
        /// <para>The default value is 30 seconds.</para></value>
        public Duration Duration
        {
            get { return (Duration)GetValue(DurationProperty); }
            set { SetValue(DurationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Duration.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="Duration"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty DurationProperty =
            DependencyProperty.Register("Duration", typeof(Duration), typeof(Carousel),
            new PropertyMetadata(new Duration(TimeSpan.FromSeconds(30)), OnDurationPropertyChanged));

        /// <summary>
        /// <see cref="Duration"/> PropertyChangedCallback function.
        /// </summary>
        /// <param name="d">The <see cref="Carousel"/> control whose <see cref="Duration"/> property changed.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs which contains the old and new values.</param>
        private static void OnDurationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Carousel carousel = d as Carousel;
            carousel.DurationChanged();
        } 
        #endregion


        #region ItemSources Property
        /// <summary>
        /// Gets or sets the collection of image used to generate the content of the control. 
        /// </summary>
        /// <value>When the carousel only display the image, you can set the Items property  a collection of image.</value>
        /// <remarks>Use this property to set the content of the <see cref="Carousel"/> when only display image.</remarks>
        public ItemSourceCollection ItemSources
        {
            get { return (ItemSourceCollection)GetValue(ItemSourcesProperty); }
            set { SetValue(ItemSourcesProperty, value); }
        }
        

        // Using a DependencyProperty as the backing store for Items.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="Items"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty ItemSourcesProperty =
            DependencyProperty.Register("ItemSources", typeof(ItemSourceCollection), typeof(Carousel),
            new PropertyMetadata(new ItemSourceCollection())); 
        #endregion   


        #region ItemWidth Property
        /// <summary>
        /// Gets or sets the carousel item width.
        /// </summary>
        /// <value>This value indicating the carousel item width.
        /// <para>The default value is 40.</para></value>
        public double ItemWidth
        {
            get { return (double)GetValue(ItemWidthProperty); }
            set { SetValue(ItemWidthProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemWidth.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="ItemWidth"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty ItemWidthProperty =
            DependencyProperty.Register("ItemWidth", typeof(double),
            typeof(Carousel),
            new PropertyMetadata(40.0, OnItemWidthPropertyChanged));

        /// <summary>
        /// The <see cref="ItemWidth"/> PropertyChangedCallback static functin.
        /// </summary>
        /// <param name="d">The <see cref="Carousel"/> control whose <see cref="ItemWidth"/> property changed.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs which contains the old and new values.</param>
        private static void OnItemWidthPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Carousel carousel = d as Carousel;
            carousel.ItemWidthChanged((double)e.NewValue);
        } 
        #endregion


        #region ItemHeight Property
        /// <summary>
        /// Gets or sets a value to specify the height of the carousel item.
        /// </summary>
        /// <value>A value specify the carousel item's height.
        /// <para>The default value is 40.</para></value>
        public double ItemHeight
        {
            get { return (double)GetValue(ItemHeightProperty); }
            set { SetValue(ItemHeightProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemHeight.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="ItemHeight"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty ItemHeightProperty =
            DependencyProperty.Register("ItemHeight", typeof(double), typeof(Carousel), new PropertyMetadata(40.0, OnItemHeightPropertyChanged));


        /// <summary>
        /// The <see cref="ItemHeight"/> PropertyChangedCallback static functin.
        /// </summary>
        /// <param name="d">The <see cref="Carousel"/> control whose <see cref="ItemHeight"/> property changed.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs which contains the old and new values.</param>
        private static void OnItemHeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Carousel carousel = d as Carousel;
            carousel.ItemHeightChanged((double)e.NewValue);
        } 
        #endregion


        #region CarouselBackground Property
        /// <summary>
        /// Gets or sets a brush to paint the carousel canvas.
        /// </summary>
        public Brush CarouselBackground
        {
            get { return (Brush)GetValue(CarouselBackgroundProperty); }
            set { SetValue(CarouselBackgroundProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CarouselBackground.  This enables animation, styling, binding, etc...
        /// <summary>
        /// Identifies the <see cref="CarouselBackground"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty CarouselBackgroundProperty =
            DependencyProperty.Register("CarouselBackground", typeof(Brush),
            typeof(Carousel), new PropertyMetadata(null, OnCarouselBackgroundChanged));

        /// <summary>
        /// <see cref="CarouselBackground"/> PropertyChangedCallback function.
        /// </summary>
        /// <param name="d">The <see cref="Carousel"/> control whose <see cref="CarouselBackground"/> property changed.</param>
        /// <param name="e">DependencyPropertyChangedEventArgs which contains the old and new values.</param>
        private static void OnCarouselBackgroundChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Carousel carousel = d as Carousel;
            carousel.CarouselBackgroundChanged((Brush)e.NewValue);
        } 
        #endregion

        /// <summary>
        /// Occurs when the user select a new item.
        /// </summary>
        public event EventHandler<SelectedItemChangedEventArgs> SelectedItemChanged;


        /// <summary>
        /// Initializes a new instance of the <see cref="Carousel"/> class.
        /// </summary>
        public Carousel()
        {
            this.DefaultStyleKey = typeof(Carousel);
            // User add,remove item from the collection
            this.ItemSources.CollectionChanged += new NotifyCollectionChangedEventHandler(Items_CollectionChanged);
        }
        

        /// <summary>
        /// Turnning one step in specifies direction.
        /// </summary>
        /// <param name="direction">The turnning direction.</param>
        /// <remarks>You can call this function only 
        /// the <see cref="AutoTurn"/> is set to <c>false</c>.</remarks>
        public void TrunOnStep(TurnDirection direction)
        {
            if (AutoTurn)
                return;
            if (CarouselCanvas != null)
            {
                double perAngle = _2PI / CarouselCanvas.Children.Count;
                foreach (var item in CarouselCanvas.Children)
                {
                    CarouselItem cItem = item as CarouselItem;
                    if (cItem != null)
                    {
                        if (direction == TurnDirection.Clockwise)
                        {
                            cItem.Angle += perAngle;
                        }
                        else
                        {
                            cItem.Angle -= perAngle;
                        }

                        // if overceed 2 PI, then adjust it
                        if (cItem.Angle > _2PI)
                        {
                            cItem.Angle -= _2PI;
                        }
                        else if (cItem.Angle < -_2PI)
                        {
                            cItem.Angle += _2PI;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Builds the visual tree for the <see cref="Carousel"/> control when a new 
        /// template is applied.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            SelectedItemViewer = GetTemplateChild(ElementSelectedItemViewerName) as ItemViewerControl;
            CarouselCanvas = GetTemplateChild(ElementCarouselCanvas) as Canvas;
            FullScreenButton = GetTemplateChild(ElementFullScreenButtonName) as Button;

            if (CarouselCanvas != null)
            {
                // Place items to carousel canvas
                PlaceItem(ItemSources);

                // Build storyboard
                Storyboard sb = BuildStoryboard(CarouselCanvas.Children, this.TurnDirection);

                if (this.AutoTurn)
                    sb.Begin();
            }
        }

        #region Private Property Changed Callback

        // The item collection changed
        private void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (CarouselCanvas != null)
            {                

                switch(e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        // Add item to collection
                        {
                            // X and Y axis of the ellipse
                            double radiusX = (this.CarouselCanvas.ActualWidth - 2 * ItemWidth
                                - (Padding.Left + Padding.Right)) / 2;
                            double radiusY = (this.CarouselCanvas.ActualHeight - 2 * ItemHeight
                                - (Padding.Top + Padding.Bottom)) / 2;

                            // center point of the ellipse
                            double centerX = radiusX + ItemWidth / 2 + Padding.Left;
                            double centerY = radiusY + Padding.Top;


                            Point center = new Point(centerX, centerY);
                            Size axis = new Size(radiusX, radiusY);

                            int count = e.NewItems.Count;
                            for (int i = 0; i < count; i++)
                            {                             

                                CarouselItem cItem = PlaceItem(e.NewItems[i] as ItemSource);
                                cItem.Center = center;
                                cItem.Axis = axis;
                            }

                            Storyboard sb = BuildStoryboard(CarouselCanvas.Children, this.TurnDirection);
                            if (this.AutoTurn)
                                sb.Begin();
                        }
                        break;

                    case NotifyCollectionChangedAction.Remove:
                        // Remove item from collection
                        {
                            int count = e.OldItems.Count;
                            for (int i = 0; i < count; i++)
                            {
                                CarouselCanvas.Children.RemoveAt(e.OldStartingIndex + i);
                            }

                            Storyboard sb = BuildStoryboard(CarouselCanvas.Children, this.TurnDirection);
                            if (this.AutoTurn)
                                sb.Begin();
                        }
                        break;

                    case NotifyCollectionChangedAction.Replace:
                        // Replace item
                        {
                            int count = e.OldItems.Count;
                            for (int i = 0; i < count; i++)
                            {
                                CarouselItem item = CarouselCanvas.Children[e.OldStartingIndex + i] as CarouselItem;
                                item.Source = (e.NewItems[i] as ItemSource).ImageSource;
                            }

                        }
                        break;

                    case NotifyCollectionChangedAction.Reset:
                        // Reset the collection
                        {
                            // do nothing
                        }
                        break;
                }
            }
        }

        //AutoTurn property chanaged
        private void AutoTurnChanged(bool turnning)
        {
            Storyboard sb = this.Resources[CarouselStoryboardKey] as Storyboard;
            if (sb != null)
            {
                if (turnning)
                {
                    sb.Begin();
                }
                else
                {
                    sb.Stop();
                }
            }
        }

        // The turnning direction changed
        private void TurnDirectionChanged(TurnDirection direction)
        {
            if (CarouselCanvas != null)
            {
                Storyboard sb = BuildStoryboard(CarouselCanvas.Children, direction);
                if (AutoTurn)
                    sb.Begin();
            }
        }

        // The turnning duration changed
        private void DurationChanged()
        {
            if (CarouselCanvas != null)
            {
                Storyboard sb = BuildStoryboard(CarouselCanvas.Children, TurnDirection);
                if (AutoTurn)
                    sb.Begin();
            }
        }

        // The carousel item width changed
        private void ItemWidthChanged(double itemWidth)
        {
            if (CarouselCanvas != null)
            {
                foreach (var item in CarouselCanvas.Children)
                {
                    CarouselItem ci = item as CarouselItem;
                    if (ci != null)
                    {
                        ci.Width = itemWidth;
                    }
                }
            }
        }

        // The carousel item height changed
        private void ItemHeightChanged(double itemHeight)
        {
            if (CarouselCanvas != null)
            {
                foreach (var item in CarouselCanvas.Children)
                {
                    CarouselItem ci = item as CarouselItem;
                    if (ci != null)
                    {
                        ci.Width = itemHeight;
                    }
                }
            }
        }

        /// <summary>
        /// The carousel canvas background changed.
        /// </summary>
        private void CarouselBackgroundChanged(Brush brush)
        {
            if (CarouselCanvas != null)
            {
                CarouselCanvas.Background = brush;
            }
        }
        #endregion

        /// <summary>
        /// Place the items to the proper position.
        /// </summary>
        /// <param name="images">The item collection will be placed.</param>
        /// <param name="canvasSize">The size of carousel canvas.</param>
        private void PlaceItem(ItemSourceCollection items)
        {
            if (CarouselCanvas != null)
            {
                // Clear all content first
                CarouselCanvas.Children.Clear();

                int imagesCount = items.Count;
                for (int i = 0; i < imagesCount; i++)
                {
                    PlaceItem(ItemSources[i]);
                }
            }
        }

        /// <summary>
        /// Place a item to carousel canvas.
        /// </summary>
        /// <param name="item">The item will be placed.</param>
        /// <returns>The <see cref="CarouselItem"/> just placed.</returns>
        private CarouselItem PlaceItem(ItemSource item)
        {
            CarouselItem cItem = new CarouselItem();
            cItem.Width = ItemWidth;
            cItem.Height = ItemHeight;
            cItem.Source = item.ImageSource;
            cItem.Tag = item;

            // Attach the handle
            cItem.MouseLeftButtonDown += new MouseButtonEventHandler(item_MouseLeftButtonDown);

            // Add item to carousel canvas
            CarouselCanvas.Children.Add(cItem);

            return cItem;
        }

        /// <summary>
        /// ReAssign angle of all items
        /// </summary>
        //private void ReAssignAngle()
        //{
        //    if (CarouselCanvas != null)
        //    {
        //        int count = CarouselCanvas.Children.Count;
        //        // Re calc the angle
        //        double perAngle = _2PI / count;
        //        for(int i=0;i<count;i++)
        //        {
        //            (CarouselCanvas.Children[i] as CarouselItem).Angle = i * perAngle;
        //        }
        //    }
        //}

        // Fire the SelectedItemChanged event
        void OnSelectedItemChanged(ItemSource item)
        {
            if (SelectedItemChanged != null)
            {
                SelectedItemChangedEventArgs e = new SelectedItemChangedEventArgs(item);
                SelectedItemChanged(this, e);
            }
        }

        // User click the item with left mouse button
        void item_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (SelectedItemViewer != null)
            {
                CarouselItem item = sender as CarouselItem;
                ItemSource source = item.Tag as ItemSource;
                SelectedItemViewer.Source = source.ImageSource;
                SelectedItemViewer.Title = source.Title;
                OnSelectedItemChanged(source);
            }
        }

        /// <summary>
        /// The carousel canvas's size changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _carouselCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // The panel width not overceed half of the canvas
            SelectedItemViewer.MaxWidth = this.CarouselCanvas.ActualWidth * 0.6;

            // X and Y axis of the ellipse
            double radiusX = (e.NewSize.Width - 2 * ItemWidth
                - (Padding.Left + Padding.Right)) / 2;
            double radiusY = (e.NewSize.Height - 2 * ItemHeight
                - (Padding.Top + Padding.Bottom)) / 2;

            //// center point of the ellipse
            double centerX = radiusX + ItemWidth / 2 + Padding.Left;
            double centerY = radiusY + Padding.Top;


            Point center = new Point(centerX, centerY);
            Size axis = new Size(radiusX, radiusY);

            foreach (var item in CarouselCanvas.Children)
            {
                (item as CarouselItem).Center = center;
                (item as CarouselItem).Axis = axis;
            }
            
        }

        /// <summary>
        /// User clicked the panel of display the selected item.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _selectedItemViewer_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            SelectedItemViewer.Source = null;
        }

        /// <summary>
        /// Full screen button clicked
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _fullScreentButton_Click(object sender, RoutedEventArgs e)
        {
            if (Application.Current.RootVisual is FrameworkElement)
            {
                FrameworkElement fe = Application.Current.RootVisual as FrameworkElement;
                rootVisualSize = new Size(fe.Width, fe.Height);
                fe.Width = double.NaN;
                fe.Height = double.NaN;
            }
            Application.Current.Host.Content.IsFullScreen = true;
        }

        /// <summary>
        /// Called when fullscreen changed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void Content_FullScreenChanged(object sender, EventArgs e)
        {
            if (Application.Current.Host.Content.IsFullScreen)
            {
                FullScreenButton.Visibility = Visibility.Collapsed;
            }
            else
            {
                if (Application.Current.RootVisual is FrameworkElement)
                {
                    FrameworkElement fe = Application.Current.RootVisual as FrameworkElement;
                    fe.Width = rootVisualSize.Width;
                    fe.Height = rootVisualSize.Height;
                }

                FullScreenButton.Visibility = Visibility.Visible;
            }
        }

        /// <summary>
        /// Build storyboard to animate the item.
        /// </summary>
        /// <param name="name">The name of the storyboard.</param>
        /// <param name="from">The from angle.</param>
        /// <param name="to">The end angle.</param>
        /// <param name="duration">The duration of the animation.</param>
        /// <returns>The builded storyboard.</returns>
        //private Storyboard BuildStoryboard(CarouselItem item, double from, double to, Duration duration)
        //{
        //    Storyboard storyboard = new Storyboard();
        //    //this.Resources.Add(name, storyboard);

        //    // Angle animation
        //    DoubleAnimation doubleAnimation = new DoubleAnimation();
        //    doubleAnimation.From = from;
        //    doubleAnimation.To = to;
        //    doubleAnimation.Duration = duration;
        //    doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

        //    // Set storyboard target property
        //    storyboard.Children.Add(doubleAnimation);
        //    Storyboard.SetTarget(doubleAnimation, item);
        //    Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Angle"));

        //    return storyboard;
        //}

        /// <summary>
        /// Build storyboard to animate the item.
        /// </summary>
        /// <param name="name">The name of the storyboard.</param>
        /// <param name="by">The total amount by which the animation changes its starting value.</param>
        /// <returns>The builded storyboard.</returns>
        private Storyboard BuildStoryboard(CarouselItem item, double by, Duration duration)
        {
            Storyboard storyboard = new Storyboard();
            //this.Resources.Add(name, storyboard);

            // Angle animation
            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.By = by;
            doubleAnimation.Duration = duration;
            doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

            // Set storyboard target property
            storyboard.Children.Add(doubleAnimation);
            Storyboard.SetTarget(doubleAnimation, item);
            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("Angle"));

            return storyboard;
        }

        /// <summary>
        /// Create the total storyboard contains all item's animations. 
        /// </summary>
        /// <param name="items">The carousel items collection.</param>
        /// <param name="direction">The carousel turnning direction.</param>
        /// <returns>The storyboard just created.</returns>
        private Storyboard BuildStoryboard(UIElementCollection items, TurnDirection direction)
        {
            // The carousel storyboard
            Storyboard sb = null;

            if (this.Resources.Contains(CarouselStoryboardKey))
            {
                // if already in resources, get from resources
                sb = this.Resources[CarouselStoryboardKey] as Storyboard;
                // Must stop it before we change it
                sb.Stop();
                // and clear the children
                sb.Children.Clear(); // because we rebuild all item
            }
            else
            {
                sb = new Storyboard();
                // Add to resources dictionary
                this.Resources.Add(CarouselStoryboardKey, sb);
            }

            // Now, we start build each item's storyboard
            int itemsCount = items.Count;
            double perAngle=_2PI / itemsCount;
            double by = _2PI;
            for (int i = 0; i < itemsCount; i++)
            {
                double angle = i * perAngle + Math.PI / 2;

                // We only care the carouselitem
                CarouselItem item = items[i] as CarouselItem;
                if (item != null)
                {
                    item.Angle = angle;

                    // Add item's storyboard to main storyboard
                    if (direction == TurnDirection.Clockwise)
                    {
                        sb.Children.Add(BuildStoryboard(item, by, Duration));
                    }
                    else
                    {
                        sb.Children.Add(BuildStoryboard(item, -by, Duration));
                    }                   
                }
            }

            return sb;
        }
        
    }
}

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 Microsoft Public License (Ms-PL)


Written By
Team Leader
China China
The God created the world.
The programer made the world easy.
I am a programer like c# and c++, so I am writting application with it.
Creating beautiful application make life easy.
If you have a project and looking for a man, I'll be say "hi, I am just the man you are looking for."

Comments and Discussions