Silverlight – Carousel in C# – So easy! – Tutorial
Here I explain how to develop a carousel to show images in a circle. You will be able to select the perspective and other parameters. This is a good tutorial and a easy to understand about silverlight.
Please refer to the newest version : http://berenger.eu/blog/2010/10/04/silverlight-a-new-carousel-working-fast-easy-to-use-with-examples/
In fact this one is buged and slow.
The Carousel
In this part I explain how to develop a generic carousel library.
The better things is to compile this library in a assembly.
Here is the code :
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;
namespace RotationManager
{
/// <summary>
/// Class to develop a carousel manager
/// Class d'un gestionnaire de Canvas en Rotation Horizontale
/// </summary>
public class HorizontalRotation
{
/// <summary>
/// Reference canvas
/// Le Canvas de travail
/// </summary>
protected Canvas working;
/// <summary>
/// Current Angle
/// Angle Actuelle
/// </summary>
protected double initial = Math.PI / 2.0;
/// <summary>
/// Objective Angle
/// Angle d'objectif
/// </summary>
protected double objectif = Math.PI / 2.0;
/// <summary>
/// Speed
/// Vitesse
/// </summary>
protected double speed = 0.0250;
/// <summary>
/// Move speed
/// Vitesse de deplacement
/// </summary>
public double Speed
{
get { return speed; }
set { speed = value; }
}
/// <summary>
/// Perspective
/// </summary>
protected double perspective = 2;
/// <summary>
/// Images perspective
/// Perspective des images
/// </summary>
public double Perspective
{
get { return perspective; }
set { if (perspective != 0) perspective = value; else perspective = 1; UpdateRotor(); }
}
/// <summary>
/// Horizontal Width
/// Largeur horizontal
/// </summary>
protected double radius_x = 250;
/// <summary>
/// Horizontal Height
/// Largeur horizontal
/// </summary>
public double RadiusX
{
get { return radius_x; }
set { if (radius_x != 0) radius_x = value; else radius_x = double.MinValue; UpdateRotor(); }
}
/// <summary>
/// Vertical Width
/// Largeur Verticale
/// </summary>
protected double radius_y = 150;
public double RadiusY
{
get { return radius_y; }
set { if (radius_y != 0) radius_y = value; else radius_y = double.MinValue; UpdateRotor(); }
}
/// <summary>
/// Center in x
/// Le centre en x
/// </summary>
protected double center_x;
public double CenterX
{
get { return center_x; }
set { center_x = value; UpdateRotor(); }
}
/// <summary>
/// Center in Y
/// Le centre en y
/// </summary>
protected double center_y;
/// <summary>
/// Le centre en y
/// </summary>
public double CenterY
{
get { return center_y; }
set { center_y = value; UpdateRotor(); }
}
/// <summary>
/// Bool to put opacity
/// Bool de changement d'opacité
/// </summary>
protected bool workWithOpacity = false;
/// <summary>
/// Changement d'opacité en fonction de la profondeur
/// </summary>
public bool WorkWithOpacity
{
get { return workWithOpacity; }
set
{
workWithOpacity = value;
if (workWithOpacity) UpdateRotor();
else
{
for (int i = 0; i < working.Children.Count; ++i)
{
working.Children[i].Opacity = 1;
}
}
}
}
/// <summary>
/// Constructor
/// Constructeur
/// </summary>
/// <param name="wk">Le canvas de travail</param>
public HorizontalRotation(Canvas wk)
{
working = wk;
for (int i = 0; i < working.Children.Count; ++i)
{
working.Children[i].MouseLeftButtonDown += new MouseButtonEventHandler(Image_MouseLeftButtonDown);
}
UpdateRotor();
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}
/// <summary>
/// Constructeur
/// </summary>
/// <param name="wk">Canvas de travail</param>
/// <param name="cx">Centre x</param>
/// <param name="cy">Centre y</param>
public HorizontalRotation(Canvas wk, double cx, double cy)
{
center_x = cx;
center_y = cy;
working = wk;
for (int i = 0; i < working.Children.Count; ++i)
{
working.Children[i].MouseLeftButtonDown += new MouseButtonEventHandler(Image_MouseLeftButtonDown);
}
UpdateRotor();
CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
}
/// <summary>
/// Move to left
/// Allez vers la gauche
/// </summary>
public void Left()
{
objectif += Math.PI * 2.0 / working.Children.Count;
}
/// <summary>
/// Move to right
/// Allez vers la droite
/// </summary>
public void Right()
{
objectif -= Math.PI * 2.0 / working.Children.Count;
}
public delegate void Clicked(UIElement elem);
public Clicked ElementClicked;
void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
initial = initial % (Math.PI * 2);
if (initial < 0) initial += Math.PI * 2;
objectif = (Math.PI / 2) - (working.Children.IndexOf((UIElement)sender) * Math.PI * 2 / working.Children.Count);
if (objectif < 0) objectif += Math.PI * 2;
if (Math.Abs(objectif - initial) > Math.PI)
{
if (initial > objectif) initial -= Math.PI * 2;
else initial += Math.PI * 2;
}
if (ElementClicked != null) ElementClicked((UIElement)sender);
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
if (Math.Abs(Math.Abs(initial) - Math.Abs(objectif)) > 0.0001)
{
if (objectif > initial)
{
initial += speed;
if (initial > objectif) initial = objectif;
}
else
{
initial -= speed;
if (initial < objectif) initial = objectif;
}
UpdateRotor();
}
}
/// <summary>
/// Update
/// Mettre a jour en fonction les positions
/// </summary>
public void UpdateRotor()
{
double angleDiff = Math.PI * 2 / working.Children.Count;
for (int i = 0; i < working.Children.Count; ++i)
{
if( workWithOpacity ) working.Children[i].Opacity = 1 + (((Math.Sin(angleDiff * i + initial) * radius_y) - radius_y) / (perspective * radius_y));
ScaleTransform sc = new ScaleTransform();
sc.ScaleX = sc.ScaleY = 1 + (((Math.Sin(angleDiff * i + initial) * radius_y) - radius_y) / (perspective * radius_y));
working.Children[i].RenderTransform = sc;
Canvas.SetLeft(working.Children[i], (Math.Cos(angleDiff * i + initial) * radius_x) + center_x - ((FrameworkElement)working.Children[i]).Width * sc.ScaleX / 2);
Canvas.SetTop(working.Children[i], (Math.Sin(angleDiff * i + initial) * radius_y) + center_y - ((FrameworkElement)working.Children[i]).Height * sc.ScaleX / 2);
Canvas.SetZIndex(working.Children[i], (int)((Math.Sin(angleDiff * i + initial) * radius_y) + 2 * radius_y));
}
}
}
}
Download the assembly : ReleaseRotation
Or download the project source : RotationManager
Use the carousel
What we have to do is add the carousel to our canvas and manage events.
In my example, I put some sliders to “test” the several controls offers by the carousel (but in our commercial engine you do not really need most of them).
Source :
namespace SilverTest
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.Loaded += new System.Windows.RoutedEventHandler(MainPage_Loaded);
}
RotationManager.HorizontalRotation rotor;
private void MainPage_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
// create rotor
rotor = new RotationManager.HorizontalRotation(RotorCanvas, Width / 2, Height / 2);
rotor.WorkWithOpacity = true;
// current event
SlidePers.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SlidePers_ValueChanged);
SlideX.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SlideX_ValueChanged);
SlideY.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SlideY_ValueChanged);
SlideSpeed.ValueChanged += new RoutedPropertyChangedEventHandler<double>(SlideSpeed_ValueChanged);
RightButton.MouseLeftButtonDown += new MouseButtonEventHandler(RightButton_MouseLeftButtonDown);
LeftButton.MouseLeftButtonDown += new MouseButtonEventHandler(LeftButton_MouseLeftButtonDown);
MouseWheel += new MouseWheelEventHandler(MainPage_MouseWheel);
}
void SlideSpeed_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
rotor.Speed = SlideSpeed.Value/10000;
}
void SlideY_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
rotor.RadiusY = SlideY.Value;
}
void SlideX_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
rotor.RadiusX = SlideX.Value;
}
void SlidePers_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
rotor.Perspective = SlidePers.Value;
}
void MainPage_MouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta > 0) rotor.Right();
else rotor.Left();
}
void LeftButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
rotor.Left();
}
void RightButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
rotor.Right();
}
}
}
The XAML of the main page is a little complicated because of the sliders.
But, the most important thing is that all the images (or user controls) are in the RotorCanvas.
<UserControl x:Class="SilverTest.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SilverTest"
Width="640" Height="480">
<Grid x:Name="LayoutRoot" Background="White">
<Canvas x:Name="RotorCanvas" Margin="8,8,8,138">
<Image Height="129" Width="129" Canvas.Left="137" Canvas.Top="65" Source="Images/jean-bleu-clair.jpg" Stretch="Fill"/>
<Image Height="129" Width="129" Canvas.Left="361" Canvas.Top="153" Source="Images/pull-blanc-mailles.jpg" Stretch="Fill"/>
<Image Height="129" Width="129" Canvas.Left="225" Canvas.Top="153" Source="Images/robe-soire-noire.jpg" Stretch="Fill"/>
<Image Height="129" Width="129" Canvas.Left="137" Canvas.Top="181" Source="Images/robe-violette-fleurs-blanches.jpg" Stretch="Fill"/>
<Image Height="129" Width="129" Canvas.Left="296" Canvas.Top="86" Source="Images/sweat-veste-zbre-vertnoir.jpg" Stretch="Fill"/>
<Image Height="107" Width="200" Canvas.Left="354" Canvas.Top="56" Source="Images/cartet.jpg" Stretch="Fill"/>
<Rectangle Height="80" Width="150" Fill="Blue" Stroke="Black"/>
</Canvas>
<Canvas x:Name="LeftButton" Height="70" HorizontalAlignment="Left" Margin="27,0,0,11" VerticalAlignment="Bottom" Width="82">
<Ellipse Fill="#FF350000" StrokeThickness="4" Height="69" Width="80">
<Ellipse.Stroke>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF9F9F9F" Offset="0"/>
<GradientStop Color="#FFE2E2E2" Offset="0.827"/>
<GradientStop Color="White" Offset="0.165"/>
<GradientStop Color="#FF6A6A6A" Offset="0.485"/>
<GradientStop Color="#FFC9C9C9" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Stroke>
</Ellipse>
<Ellipse StrokeThickness="0" Height="61" Width="72" Canvas.Left="4" Canvas.Top="4">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA10000" Offset="0"/>
<GradientStop Color="#FFFF7F5B" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse StrokeThickness="0" Height="25" Width="47" Canvas.Left="17" Canvas.Top="5">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#CCFFFFFF" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Ellipse StrokeThickness="0" Height="61" Width="72" Canvas.Left="4" Canvas.Top="4">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#00A10000" Offset="0.456"/>
<GradientStop Color="#B2FF9D5B" Offset="1"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<TextBlock Height="36" Width="80" Canvas.Top="17" FontFamily="Arial Black" FontSize="18.667" Text="Left" TextAlignment="Center" TextWrapping="Wrap"/>
</Canvas>
<local:ButtonGloss x:Name="RightButton" Height="73" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="85"/>
<Slider x:Name="SlideX" Height="22" Margin="236,0,145,72" VerticalAlignment="Bottom" Maximum="500" Minimum="1" Value="250"/>
<Slider x:Name="SlideY" Height="22" Margin="236,0,145,46" VerticalAlignment="Bottom" Maximum="500" Minimum="1" Value="150"/>
<Slider x:Name="SlidePers" Height="22" Margin="236,0,145,20" VerticalAlignment="Bottom" Maximum="20" Minimum="1" Value="2"/>
<TextBlock Height="22" HorizontalAlignment="Left" Margin="146,0,0,72" VerticalAlignment="Bottom" Width="66" Text="Rayon X" TextWrapping="Wrap"/>
<TextBlock Height="22" HorizontalAlignment="Left" Margin="146,0,0,46" VerticalAlignment="Bottom" Width="66" TextWrapping="Wrap"><Run Text="Rayon "/><Run Text="Y"/></TextBlock>
<TextBlock Height="22" HorizontalAlignment="Left" Margin="146,0,0,20" VerticalAlignment="Bottom" Width="66" Text="Perspective" TextWrapping="Wrap"/>
<Slider x:Name="SlideSpeed" Height="22" Margin="236,0,145,-2" VerticalAlignment="Bottom" Maximum="500" Minimum="1" Value="1"/>
<TextBlock Height="22" HorizontalAlignment="Left" Margin="146,0,0,-2" VerticalAlignment="Bottom" Width="66" Text="Vitesse" TextWrapping="Wrap"/>
</Grid>
</UserControl>
Download the project : SilverTest
To finish
Maybe your site is not in silverlight from top to bottom.
Something that can be great is passing the images in html param to the xap and call a javascript function after a user clicked.
I let you do that by your self.
If you want to use transparency there is a post on my blog about that.
Please leave comments.
Subscribe to the RSS feed and have all new posts delivered straight to you.
