(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Image slider control in Silverlight

(26 votes)
Denislav Savkov
>
Denislav Savkov
Joined Feb 11, 2008
Articles:   14
Comments:   6
More Articles
35 comments   /   posted on Feb 29, 2008
Categories:   Controls

This article is compatible with the latest version of Silverlight.

Overview

 
In this article we will present an animated image slider that we made for SilverlightShow.net. We will use it in our highlight control, which will be ready soon and will replace the highlights on our front page. Our goal is to have a slider which loads images from Uri location and shows a limited number of them. It also should use transition animation to switch between hidden and visible images.


Download source code

Principle

 
The basic things we need are two buttons to slide left and right and a canvas, which contains the visible images. But we also want an image to be selectable so we’ll have a rectangle to indicate the selected image. And this is enough to contain and present our images.
 
When it comes to implementation of the sliding animation we thought of two approaches.
  • We load all images and position them one after the other. Then we show only a number of them and we move all images so some of them begin to appear and some of them begin to disappear from the control.
  • How we implemented the control – we load only the images which are showed and every time we slide we accomplish a visual illusion.
In short we have: transition animation (1-2), reloading new images (2-3), restoring original position (3-4). The loading and the restoring of their original positions is done very quick so (3) can’t be seen and the user sees no change. (The visible area for the user is between the two orange lines.)

1.

2.

3.

4.

User sees 1, 2, 3, 4.
 
This implementation resembles what we would normally do if we wanted to scroll through images without animation – just have a number of Imageobjects and change their Source property. Actually, we are doing just that but immediately after the animation.
 
 

Implementation

 
For each image that we animate we use AnimationImage class. It extends Control and contains one Image and two Storyboard objects. Using Storyboard we do transformations of different objects in time. A Storyboard contains animations, one animation for each property that we want to animate. This means we have one Storyboardfor animating left movement and one for right.
 
 <Canvas.Resources>
    <Storyboardx:Name="left">
      <DoubleAnimationStoryboard.TargetName="image"Duration="0:0:0.2" Storyboard.TargetProperty="Canvas.RenderTransform.TranslateTransform.X"
                   By="0"
                   x:Name="translateLeft"/>
    Storyboard>
    <Storyboardx:Name="right">
      <DoubleAnimationStoryboard.TargetName="image"Duration="0:0:0.2"
 Storyboard.TargetProperty="Canvas.RenderTransform.TranslateTransform.X"
                 By="0"
                 x:Name="translateRight"/>
    Storyboard>
 Canvas.Resources>
 
And want to can change By so we get C# object in the constructor of the control:
 
. . .
leftAnimation = this.parentCanvas.FindName( "left" ) as Storyboard;
translateLeft = leftAnimation.Children.FindName( "translateLeft" ) asDoubleAnimation;
. . .
 
And we make this property changeable in C#:
 
      public double AnimateBy
        {
            get { return (double)translateLeft.By; }
            set
            {
                translateLeft.By = - value;
                translateRight.By = value;
            }
        }
 
We also want to know when the animation is over and when an image is clicked so we hook these three events:
 
image.MouseLeftButtonUp
+= new MouseEventHandler(ImageMouseLeftButtonUp);
leftAnimation.Completed += new EventHandler( AnimationLeftCompleted );
rightAnimation.Completed += new EventHandler( AnimationRightCompleted );
 
Now we are ready to use this class in our ImageSlide. Besides moving images we need buttons for left and right, and frame to indicate the user’s selection. To implement buttons we wrote ActionButton, which has disabled and enabled state and image for each of them.
 
public bool IsDisabled
{     set
         {
            isDisabled = value;
            if( value )
            {
                disabledImage.Visibility = Visibility.Visible;
                enabledImage.Visibility = Visibility.Collapsed;
            }
            else
            {
                enabledImage.Visibility = Visibility.Visible;
                disabledImage.Visibility = Visibility.Collapsed;
            }
        }
}
 
Now let’s talk more on the slide itself. We want the images to slide from outside the visible area. This means we need to have two more moveable images than the number of images we want to display. On the following picture we have additional image on the right and no additional on the left. Now imagine we slide this to left and to right. (Remember after the slide we bring the images to their original position.)

 

 
This leads to the problem that first and last images can’t be seen. The problem is easily solved by adding two additional images in the Uri collection from which we are loading images.
 privateCollection<Uri> locationsList;
These additional images are never shown in the visible are of the user.
The animations we are using are kept in a collection too:
privateCollection<AnimationImage> animationsList;
Since we are loading images each time we slide we need to load them fast from the memory, so we use a collection of Image objects to cache the image content:
privateCollection<Image> imagesList;
Each time we slide, a new image is loaded in the cache if it isn’t there yet.
 
private void ReloadVisibleImages()
{
    while( offset + animationsList.Count > imagesList.Count )
    {
        imagesList[ imagesList.Count - 1 ].Source
                             = locationsList[ imagesList.Count - 1 ];
        imagesList.Add( new Image() );
    }
    imagesList[ imagesList.Count - 1 ].Source
                             = locationsList[ imagesList.Count - 1 ];
      for( int i = 0 ; i < animationsList.Count ; i++ )
      {
     animationsList[ i ].ImageSource = imagesList[ i + offset ].Source;
      }
}
 
Now let’s see how we are adding new images to the list.
 

public void AddImage( Uri fileUrl )
{
    //we change the last image to the new
    locationsList[ locationsList.Count - 1 ] = fileUrl;
    //add new empty image to "push" the last image into the visible area
    //this image is never seen
    locationsList.Add( newUri( "images/empty.png", UriKind.Relative ));
    //there are alway 2 images outside the visible area, so
    //if we have more than 3 in the list we need to enable the right
    //buttonfor pushing
    if( locationsList.Count > 3 )
        RightButton.IsDisabled = false;
    //This we will explain next
    if ( visibleImagesTargetCount >= locationsList.Count )
    {
        animatedImagesCount++;
        Width = ( animatedImagesCount - 2 ) * ( imageWidth + ( 2 * Margin ) ) + LeftButton.Width + RightButton.Width;
        parentCanvas.Width = Width - LeftButton.Width - RightButton.Width;
        dataCanvas.Width = Width - LeftButton.Width - RightButton.Width;
        clippingRect.Width = Width - LeftButton.Width - RightButton.Width;
        RefreshSize();
        RefreshVisibleImagesCount();
        clippingGeometry.Rect = clippingRect;
    }
    //Sets the last animation on the right the correct image
    animationsList[ animationsList.Count - 1 ].ImageSource = locationsList[ animationsList.Count - 1 ];
}
 
Here we see the int visibleImagesTargetCount. Each time the user of the control adds new image we add new animated image. This is true until we reach the desired number of animated images we want (the user) to be shown. visibleImagesTargetCount is this desired number.What we have in the last if block is adding animated image and resizing the control.
Here is how we keep track of how many animations are desired
 
        public int VisibleImages
        {
            get { return animatedImagesCount - 2; }
            set
            {
                animatedImagesCount = value + 2;
                visibleImagesTargetCount = value + 2;
                if ( animatedImagesCount > locationsList.Count )
                    animatedImagesCount = locationsList.Count;
                RefreshSize();
                RefreshVisibleImagesCount();
            }
        }
 
In case we don’t have enough locations of images we cut the animated images to the number we have and later we add animated images later in the code above the last.
 
After we have added images and the control is initialized we may start sliding. In case the user clicks on an image we simply change the selection
 
void ImageClicked( object sender, MouseEventArgs e )
{
    SelectedVisibleImageIndex = ( int )( e.GetPosition( dataCanvas ).X / ( imageWidth + 2 * Margin ) );
            selectionFrame.Reset();
      selectionFrame.SetValue<double>( Canvas.LeftProperty,
        ( int )( value * ( imageWidth + 2 * Margin ) ) );
 
. . .
 
And send message to the consumer of the control
 
private int SelectedVisibleImageIndex
{
    set
    {
        selectedVisibleImageIndex = value;
        if( this.SelectionChange != null )
            this.SelectionChange( this,
       new SelectedItemChanged( offset + selectedVisibleImageIndex ) );    }
 
It is more interesting to see what happens when the user clicks on the left/right button. It is clear that the animation is done here but since we are depending on the animation to complete we need to lock the buttons until all animations are done, and this way all the AnimatedImage object have loaded new images.
 
private void MoveToRight( object sender, MouseEventArgs e )
{
    // current animanition is not finished
    if( readyAnimationsCount != animationsList.Count )
        return;
 
Next we check if we have reached the last image the user is supposed to see. I we haven’t we start the animation.
 
    if( offset + animatedImagesCount < locationsList.Count )
    {
        offset++;
        SelectedImage -= 1; // change the selection
    // slide the selection frame if it is visible
    if( SelectedImage >= -1 && SelectedImage < animatedImagesCount - 1 )
      selectionFrame.AnimateLeft();
        readyAnimationsCount = 0;
        isReloading = true;
        foreach( AnimationImage i in animationsList )
            i.AnimateLeft(););// slide the images
        LeftButton.IsDisabled = false;
    }
 
If we have reached the end and we have selected the last image we need to disable the button.
 
    if( offset + SelectedVisibleImageIndex + 1 == locationsList.Count - 2)
            RightButton.IsDisabled = true;
}
 
Now we have started the animation. For each animation we receive a message on its completion. When the last animation is completed readyAnimationsCount is equal to animationsList.Count and so the button is unlocked.
 
private void ImageAnimationCompleted( object sender, AnimationImageEventArgs e )
{
    readyAnimationsCount++;
    if( isReloading )
    {
        isReloading = false;
        ReloadVisibleImages();
    }
}
 
We need to reload the images immediately after the animations completion but only once so we change isReloading to false.
 

Summary 

At first sight a slider isn’t something complicated but adding animation to it makes things a little different. The design of our solution is probably not the best but the control is not breaking the illusion even when the CPU is under heavy load. It would be better if the loading is done out of the visible area of the control. Still we didn’t catch any problems but if you see any, don’t hesitate to notify us or leave your comments.

Subscribe

Comments

  • -_-

    RE: Image slider control in Silverlight 1.1


    posted by Mark on May 27, 2008 10:01

    Can you guys fix the demo?

  • emil

    RE: Image slider control in Silverlight 1.1


    posted by emil on May 27, 2008 22:55

    Mark, yes we will update the demo to work with Silverlight 2. Stay in touch within the end of the week and it will be updated.

  • -_-

    RE: Image slider control in Silverlight 1.1


    posted by Doraemon on Jun 10, 2008 21:53

    Do you have Silverlight 2 Beta 1 version? Demo and codes not running :(

  • emil

    RE: Image slider control in Silverlight 1.1


    posted by emil on Jun 11, 2008 03:55

    Doraemon, yes we are working on updating the source code and the demo to work in beta 2. We will announce it as soon as we are ready. Thank you for your interest. 

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Ola on Jun 20, 2008 06:53

    Interesting article, looking forward to seeing the Beta 2 version :)

  • emil

    RE: Image slider control in Silverlight 2


    posted by emil on Jun 20, 2008 10:13

    Ola, the control is already ported to beta 2. Go ahead and use it ;)

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Denny on Jun 22, 2008 08:58

    I think I see a bug / typo in the code, I have not run it as I am trying to use the code to learn from.

    in SliderControl.xaml.cs line 51 I see

    public new Brush Background { ... }

    as this is a property Get / Set I guess the "new" is an error.

     

  • -_-

    RE: Image slider control in Silverlight 2


    posted by denny on Jun 22, 2008 09:05

    also you have a private pair of properties with the same odd new double

    for width and hight ... again, is this an error or some new form of property syntax ??

  • -_-

    RE: Image slider control in Silverlight 2


    posted by denny on Jun 22, 2008 10:43

    Ah.... My bad , Hiding the base property!

    might be worth adding a comment to say that's why it's built that way.

  • -_-

    RE: Image slider control in Silverlight 2


    posted by denny on Jun 22, 2008 10:48

    By the way, what I am hoping to do is:

    have a general "Slider" that can go up/down or left/right and to make the control work with a nt just images, slide buttons, images, usercontrols, etc...

    and make the size of the control a property, width,height etc...

  • emil

    RE: Image slider control in Silverlight 2


    posted by emil on Jun 22, 2008 22:17

    denny,

    Thanks for your comments. The "general slider" you are talking about is a very good idea. The time when this image slider control was released Silverlight was still in its Alpha state and it was hard to talk about templating, etc. But now it is pretty common to talk about more general slider control. I think it does worth to build such - we are going to think about that idea.

  • -_-

    RE: Image slider control in Silverlight 2


    posted by aquaseal on Jun 30, 2008 09:41

    Great control! I modified the control a little bit and added repeatbuttons instead of images on the scrolling for faster scrolling through a large collection. Here is my sample app:

    http://www.theamoebaproject.com/blog/aquaseal/deep-zoom-selecting-image

    Thanks again!

  • -_-

    RE: Image slider control in Silverlight 2


    posted by vik on Jul 07, 2008 02:14

    Very useful control.Thanks a lot!

    Is it possible to put a selection/deselection sign (like a red cross) on the top of the image to remove it from the collection. The way it has been implemented in Fluxify :

    http://fluxcapacity.net/fluxtools/emailphotos/

    Thanks!

     

  • Enrai

    RE: Image slider control in Silverlight 2


    posted by Enrai on Jul 08, 2008 00:05

    Yes, it's possible. In the AnimationImage.xaml file in the Canvas control named "container" put a button for example and align it properly with the image (that depends on the width and the height of the image). Than create an EventHandler for the button click event. In this handler you should raise an event to be handled in the ImageScroll. There you can remove the selected image from the collections. Note that this version of the ImageSlider was meant to be read-only, but now we're working on adding functionality and making the control easily extendable.

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Dilip on Jul 26, 2008 12:19

    Hi,

    I need revolving objects (images) automatically without user clicking the arrows at either end. Automatically the image should resolve and when we point the mouse it should zoom. Does anybody has any pointers how to accomplish this? Btw, I'm newbie to Silverlight

    Thanks in advance.

     

     

  • dejo

    RE: Image slider control in Silverlight 2


    posted by dejo on Jul 28, 2008 06:57

    Dilip, here are your answers:

    You need to do what aquaseal did a few posts ago. You shold replace the ActionButton with RepeatButton and instead of hooking on Click hook on MouseEnter.

    About the zooming images that's possible too. When we initially started working on this Image Slider Silverlight was in Alpha version (as you may see from the URL of this article 1.1). Now in Beta 2 there is a ContentControl that can contain any kind of control. We posted an article about customizing such control so that you can apply the same animation to whatever object you put inside this control. You may include the CustomContentControl from this article and replace the Image in AnimationButton.xaml with CustomContentControl. You also should make a few slight modifications to set ContentContol.Content instead of Image.Source. I tried that and it works except there is some of those unknown errors (4001) and I'm not sure why is that. It works on IE if you ignore the errors but crashes FF. We may investigate if we have time but now we are working on new slider that takes advantage of the new features of Beta 2 and you will see just  what you want there.

    Here is the article from where you can get zooming control, just modify the xaml:

    http://www.silverlightshow.net/items/Custom-ContentControl-using-VisualStateManager.aspx

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Tibo on Aug 08, 2008 15:49

    Great control, but how do you change remove images programmaticaly? I want to use only one component to display multiple albums.

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Andrew Ames on Sep 26, 2008 02:01

    How would i extend this to allow me to drag and drop the images somewhere? i don't want to remove them from the collection/slider, just drag it on to say another image control, then that control displays the same image?

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Raj on Nov 05, 2008 22:44

    Hi,

    We have  used the image slider in your project  and the application works fine in IIS . But when  host ed on tomcat server the  left and right buttons are not visible after the 3 images on the slider.  Deos this kind of problem occurred to any anybody  and any idea how to reslove this.

    Thanks in advance.

     

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Akku on Dec 02, 2008 15:21

    Hi,

    I want to add some information about each image in the image slider control as a tool tip to the image like place and date I clicked that picture. I have added handler on MouseEnter event at the time image get added to visibleimage list,  like this

    MouseEntered(object sender, MouseEventArgs e)

    void

    {//ToolTipService.SetToolTip((AnimationImage)sender, ((AnimationImage)sender).Tag.ToString());ToolTipService.SetToolTip((AnimationImage)sender, "Tooltip On MouseEnter");

    some how it is not coming up, any suggestion on this.

    Thanks in advance 

     

     

    }

  • -_-

    RE: Image slider control in Silverlight 2


    posted by JC on Apr 21, 2009 10:19

    Can someone show me the best way to display a title under each image in this slider, I am so confused.

     

    TYIA

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Kenny Haynes on Apr 27, 2009 00:08
    Can someone please tell me how to size the image? I cannot figure out how to set the size of each image. I have played with this projkect and can size everything else but each image. when I play with all width properties say like image width it just changes the blue box, but not the image. Any ideas?
  • -_-

    RE: Image slider control in Silverlight 2


    posted by jewelthief on Jun 18, 2009 00:53
    I want vertical slider not horizontal. how can I quickly do that?
  • -_-

    RE: Image slider control in Silverlight 2


    posted by Brian on Jul 14, 2009 19:17
    The transitions for this control utilizes the X coordinate.  If you want to move vertical then the animation needs to animate the Y coordinate for the translate transform.  That should get on the right track for making it vertical.
  • -_-

    RE: Image slider control in Silverlight 2


    posted by Slizka on Dec 12, 2009 23:53
    Not really helpful for beginers :(
  • -_-

    RE: Image slider control in Silverlight 2


    posted by Bolek on Dec 12, 2009 23:54
    Next time put more comments in your sourcecode
  • -_-

    RE: Image slider control in Silverlight 2


    posted by Mahesh on Mar 04, 2010 14:30

    Hi,

    I have to do one task about image slider which matches with your current example.

    But  one small change that I have a collection of the Images and i want to directly bind the collection to the Image Rotator.

    Because many times it happens that i am going to add new images into Image Collection or remove images from collection.

     I am using observable collection, because of that no need to explicitely add the images into Image Rotator.

    Can you please suggest me a workaround about same?

    Or If you have some sample solution which same example which willl work with direclty collection.

    Thanks in Advance.

  • -_-

    RE: Image slider control in Silverlight 2


    posted by UptownGirl on Mar 09, 2010 23:54
    Is there a way to get the arrow buttons to be on top of the images instead of on the ends of an image? I've modified it for a larger rectangular image but I want the buttons to float above the image not on the side creating that white space gap. Any help is appreciated Thanks.
  • -_-

    RE: Image slider control in Silverlight 2


    posted by Kronos on Apr 11, 2010 05:18

    Hi!

    What can I do if I want to move more than one image with one click (moving 5 images at the time)?

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Tony Springs on May 08, 2010 19:14
    Why doesn't Microsoft announce that they are NOT supporting Visual Basic anymore. Seems like every sample and any code written with Silverlight is in C# and us VB programmers have to beg to get the code also written in VB.
    I think there is still a hugh percentage of coders using VB, and we should not be slighted like this by anyone.
    Hope you consider adding VB support to your blog.
    Tony
  • -_-

    RE: Image slider control in Silverlight 2


    posted by Jenn on May 28, 2010 03:33

    I would also like to know how to reposition the right and left buttons. I tried using "Canvas.SetLeft" and "Canvas.SetTop" for the buttons in the ImageScroll() constructor, but it didn't seem to have any effect.

    Otherwise, I really like this scroller!

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Jenn on May 28, 2010 03:55

    I would also like to know how to reposition the right and left buttons. I tried using "Canvas.SetLeft" and "Canvas.SetTop" for the buttons in the ImageScroll() constructor, but it didn't seem to have any effect.

    Otherwise, I really like this scroller!

  • -_-

    RE: Image slider control in Silverlight 2


    posted by Rame on Jun 08, 2010 07:34

    Hi,

    I would like to do some changes in this image slider control.Changes are:
    I need to place a dropdown control (e.g category drp)above the image slider and if user select any value in drp the images in slider control should clear and updated with new images depend upon the selection of drp. I tried in this downloaded code, but I can't.

    It was urgent. Any help please and thanks in advance.

  • -_-

    RE: Image slider control in Silverlight 2


    posted by AvishekRC on Jul 19, 2010 14:00

    Hi,

    Its exactly what I want for my requirement.

    However,Can you please tell le how to use this application in my ASP.Net web application?

    Should I:

    1.Copy-Paste  each and every pages in my ASP.Net application manually?

    2.Or can I add the dll and use it ready made.I have added the dll,but got stuck,how to use it?

     

  • dipti259

    Re: Image slider control in Silverlight


    posted by dipti259 on Dec 05, 2011 12:44

    Hi Enrai,

    I am using your control in my application, I really like your control.

    One enhancement I wanna make is: instead of a selection frame, I wanna load another image on selection (so when an image is selected, a different image is displayed and when another image is clicked, the previous selection goes back to normal and another image is displayed on currently selected image). How do i do so?

    This means to say that I have two set of images, one for non-selection and one set of images for selection.

    Thanks.

Add Comment

Login to comment:
  *      *