Home > Developer, Expression, Info, Silverlight > Image Carousel in Silverlight

Image Carousel in Silverlight

Ein großes Hobby von mir sind Steuerelemente für Silverlight. Es gibt extrem viele tolle Beispiele an Tricks und Effekten in Silverlight. Doch leider sind diese sehr oft nur schwer übertragbar, da es sich dabei um Spaghetti-Code handelt oder hart-verdrahtete Konstanten verwendet werden.

Im heutige Beispiel erstelle ich ein Bilderkaroussel das man dynamisch anpassen kann, so wie man es von “echten” Steuerelementen gewohnt ist.

image

In Blend hat kann man nun beliebige Bilder einfügen, anpassen und sortieren.

image

Der Objektbaum wird dabei im Objects&Timeline-Bereich ordentlich dargestellt.

Der gesamte Sourcecode:

using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace TheOliver.Controls
{
    public class ImageSpindle : Panel
    {
        Point _mousePoint;
        double _height;
        double _width;
        bool _isMouseOver;

        public ImageSpindle()
        {
            this.Loaded += (s, e) =>
                {
                    if (DesignerProperties.GetIsInDesignMode(this))
                    {
                        return;
                    }

                    this.MouseMove += (s1, e1) =>
                        {
                            _mousePoint = e1.GetPosition(this);
                        }; 

                    CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
                };

            this.MouseEnter += (s, e) =>
                {
                    _isMouseOver = true;
                };

            this.MouseLeave += (s, e) =>
                {
                    _isMouseOver = false;
                };
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            _height = availableSize.Height;
            _width = availableSize.Width;

            var images = this.Children.OfType<Image>();
            int imageCount = images.Count();
            if (imageCount > 0)
            {
                double step = 360.0 / imageCount;
                double currentStep = 0;
                foreach (var image in images)
                {
                    UpdateImage(image, currentStep);
                    currentStep += step;
                }
            }
            return base.MeasureOverride(availableSize);
        }

        private Image UpdateImage(Image image, double step)
        {
            image.Height = ImageHeight;
            image.Width = ImageWidth;
            image.Margin = new Thickness(
                (_width - ImageWidth) / 2, (_height - ImageHeight) / 2,
                (_width - ImageWidth) / 2, (_height - ImageHeight) / 2);
            image.RenderTransformOrigin = new Point(0.5, 0.5);
            image.Stretch = ImageStretch;

            PlaneProjection pp = new PlaneProjection();
            pp.CenterOfRotationZ = SpindleCenterOfRotation;
            pp.RotationY = step;
            image.Projection = pp;

            return image;
        }

        void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if (StopWhenMouseLeft)
            {
                if (!_isMouseOver)
                {
                    return;
                }
            }

            if (double.IsNaN(_width) || _width == 0)
            {
                return;
            }

            foreach (var image in this.Children.OfType<Image>())
            {
                PlaneProjection pp = image.Projection as PlaneProjection;
                if (pp != null)
                {
                    pp.RotationY += ((_mousePoint.X - (_width / 2)) / _width) * 10;
                }
                image.Opacity = (_mousePoint.Y / _height) * 0.5 + 0.5;
            }
        }

        #region Properties

        public Stretch ImageStretch
        {
            get { return (Stretch)GetValue(ImageStretchProperty); }
            set { SetValue(ImageStretchProperty, value); }
        }

        public static readonly DependencyProperty ImageStretchProperty =
            DependencyProperty.Register(
                "ImageStretch",
                typeof(Stretch),
                typeof(ImageSpindle),
                new PropertyMetadata(Stretch.Uniform, OnValueChanged));

        public double ImageWidth
        {
            get { return (double)GetValue(ImageWidthProperty); }
            set { SetValue(ImageWidthProperty, value); }
        }

        public static readonly DependencyProperty ImageWidthProperty =
            DependencyProperty.Register(
                "ImageWidth",
                typeof(double),
                typeof(ImageSpindle),
                new PropertyMetadata(160.0, OnValueChanged));

        public double ImageHeight
        {
            get { return (double)GetValue(ImageHeightProperty); }
            set { SetValue(ImageHeightProperty, value); }
        }

        public static readonly DependencyProperty ImageHeightProperty =
            DependencyProperty.Register(
                "ImageHeight",
                typeof(double),
                typeof(ImageSpindle),
                new PropertyMetadata(120.0, OnValueChanged));

        public double SpindleCenterOfRotation
        {
            get { return (double)GetValue(SpindleCenterOfRotationProperty); }
            set { SetValue(SpindleCenterOfRotationProperty, value); }
        }

        public static readonly DependencyProperty SpindleCenterOfRotationProperty =
            DependencyProperty.Register(
                "SpindleCenterOfRotation",
                typeof(double),
                typeof(ImageSpindle),
                new PropertyMetadata(-160.0, OnValueChanged));

        private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ImageSpindle spindle = sender as ImageSpindle;
            spindle.InvalidateMeasure();
        }

        public bool StopWhenMouseLeft
        {
            get { return (bool)GetValue(StopWhenMouseLeftProperty); }
            set { SetValue(StopWhenMouseLeftProperty, value); }
        }

        public static readonly DependencyProperty StopWhenMouseLeftProperty =
            DependencyProperty.Register(
                "StopWhenMouseLeft",
                typeof(bool),
                typeof(ImageSpindle),
                new PropertyMetadata(true));

        #endregion

    }
}

Dieses und weitere Controls befinden sich in meiner Control-Bibliothek unter http://theolivercontrols.codeplex.com/ Viel Spaß

Categories: Developer, Expression, Info, Silverlight Tags:
  1. Stefan
    March 9th, 2010 at 18:10 | #1

    Das Carousel funktioniert einwandfrei, sobald man genügend bilder hat. Wenn es weniger sind, dann hakt es ein wenig… Gut sind die Einstellmöglichkeiten gelungen :)

    Der Link auf dem Codeplex-Projekt scheint aber nicht zu funktionieren:
    “You can see the controls in action here: http://os75.com/controls/samples.html

    mfg

  1. No trackbacks yet.