Create an automatic scrollable image slider in Silverlight

I guess someone will send me an comment and say something like: “Why not simply use XXXX, why write your own control” ;) I know there are a lot of controls out there that will do stuff for me, but I want to know how they are created, and try to create my own solution to learn more etc.

I’m working on a small and relative simple Silverlight app for my brother, and I wanted to make it possible for the users to see the images as thumbnails (he is a photographer on his spare time and want a site to show his works). The thumbnails should be placed after each other horizontal in a  scrollable list, the list should be scrollable automatically.

image


You can see the list of Thumbnails at the bottom of the image above. I wanted the list of Thumbnails to be scrollable, but not by moving a scrollbar, instead an automatic scrolling when the mouse is heading to the right or left side of the list. I was first thinking of using a Canvas and use the Canvas.Top and Left attached property to scroll the thumbnails, but I decided to take advantage of the ScrollViewer control. The problem with the ScrollViewer is that we don’t have a property to set the scrollers’s position, instead we have to use the ScrollToHorizontalOffset method. So I couldn’t define an animation for handling the scrolling, instead I decide to use the DispatchTimer class and handle the “animation” on my own.

private DispatcherTimer _thumbnailScrollTimer = new DispatcherTimer();

public AutomaticImageSlider()
{
      InitializeComponent();

       _thumbnailScrollTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
       _thumbnailScrollTimer.Tick += new EventHandler(_thumbnailScrollTimer_Tick);
}

The reason I used the DispathTimer is because every time it ticks based on an interval an event is trigged, the event handler for the Tick will be executed on the UI thread. I set the interval of the Timer control to 1 millisecond, this value can of course be changed, based on how fast and often I want to update the ScrollViewer. I put my ScrollViewer inside of a StackPanel, and hooked up to the StackPanel’s MouseMove event.

<StackPanel
        x:Name="thumbnailViewer"
        MouseMove="thumbnailViewer_MouseMove"
        HorizontalAlignment="Center"
        VerticalAlignment="Bottom"
        Background="Black">

            <ScrollViewer
                x:Name="thumbnailViewerScroller"
                Padding="0"
                BorderThickness="0"
                VerticalScrollBarVisibility="Hidden"
                HorizontalScrollBarVisibility="Hidden">
                
               <!-- Images here, I add the images dynamically -->
            
            </ScrollViewer>

</StackPanel>

I only wants to start the timer when I move the mouse over a specific part of the StackPanel, so when the mouse are in the middle part of the ScrollViewer the timer should be idle (stopped). The MouseMove event will check if the mouse is within a specific position and if it is, the ScollViewer should start to scroll until it reached the end of its content or the mouse is leaving the area.

private void thumbnailViewer_MouseMove(object sender, MouseEventArgs e)
 {
      var x = e.GetPosition(sender as UIElement).X;

       if (x >= 300 && x <= 700)
       {
            _acceleration = 0;
            _thumbnailScrollTimer.Stop();
            _thumbnailScrollTimerStarted = false;
       }
       else
       {
            if (x > 700)
                 _acceleration = (int)(Math.Pow((x - 512), 1.5) / 1200);
            else if (x < 300)
                 _acceleration = -(int)(Math.Pow((512 - x), 1.5) / 1200);

            if (!_thumbnailScrollTimerStarted)
                 _thumbnailScrollTimer.Start();

            _thumbnailScrollTimerStarted = true;
        }
  }

By using the MouseEventArgs’s GetPosition method, I can get the position of the mouse. If the mouse is between X 300 and 700, the ScrollView should stand still and the timer should be stopped. If the mouse X position is between 0 – 300, the ScrollViewer should start to scroll to the right direction, if the mouse X position is larger than 700, the ScrollViewer should start scrolling to the Left direction. I have a private field with the name _acceleration, it’s how fast the ScrollViewer should be moving. The acceleration will increased based on the mouse X position. This will create a smother and more user friendly scrolling. My acceleration calculation code is based on a fixed width of the ScrollViwer, the width is set to 1024 pixels. I use Math.Pow to make sure the acceleration should not be linear. As you can see, the MouseMove will start the timer. The Tick event of the timer will make sure to move the ScrollViewer’s scroller.

void _thumbnailScrollTimer_Tick(object sender, EventArgs e)
{
     thumbnailViewerScroller.ScrollToHorizontalOffset(thumbnailViewerScroller.HorizontalOffset + _acceleration);

     if (thumbnailViewerScroller.HorizontalOffset + _acceleration <= 0)
        _thumbnailScrollTimer.Stop();
}

I use one if statement to make sure the Timer will stop when the ScrollViewer’s scroller is at the beginning of the ScrollViewer. I should also have one if it reaches the end of the ScrollViewer, but I don’t really know when it reaches the end, the HorizontalOffset value it’s based on the ScrollerViewer’s content, and that content can vary.

Here is the code of a full working example:

MainPage.xaml

<UserControl x:Class="SilverlightApplication7.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" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">


        <StackPanel
        x:Name="thumbnailViewer"
        MouseMove="thumbnailViewer_MouseMove"
        Background="Black" Height="208" Width="1024">

            <ScrollViewer
                x:Name="thumbnailViewerScroller"
                Padding="0"
                BorderThickness="0"
                VerticalScrollBarVisibility="Hidden"
                HorizontalScrollBarVisibility="Hidden">

                <StackPanel Orientation="Horizontal">
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                    <Rectangle Width="200" Height="200" Fill="Red" Margin="4"></Rectangle>
                </StackPanel>
            
            </ScrollViewer>

        </StackPanel>
  </Grid>
</UserControl>


MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace SilverlightApplication7
{
    public partial class MainPage : UserControl
    {
        private int _acceleration = 0;
        private bool _thumbnailScrolltTimerStarted;
        private DispatcherTimer _thumbnailScrollTimer = new DispatcherTimer();

        public MainPage()
        {
            InitializeComponent();

            _thumbnailScrollTimer.Interval = new TimeSpan(0, 0, 0, 0, 1);
            _thumbnailScrollTimer.Tick += new EventHandler(_thumbnailScrollTimer_Tick);

        }

        void _thumbnailScrollTimer_Tick(object sender, EventArgs e)
        {
            thumbnailViewerScroller.ScrollToHorizontalOffset(thumbnailViewerScroller.HorizontalOffset + _acceleration);

            if (thumbnailViewerScroller.HorizontalOffset + _acceleration <= 0)
                _thumbnailScrollTimer.Stop();
        }


        private void thumbnailViewer_MouseMove(object sender, MouseEventArgs e)
        {
            var x = e.GetPosition(sender as UIElement).X;

            if (x >= 300 && x <= 700)
            {
                _acceleration = 0;
                _thumbnailScrollTimer.Stop();
                _thumbnailScrolltTimerStarted = false;
            }
            else
            {
                if (x > 700)
                    _acceleration = (int)(Math.Pow((x - 512), 1.5) / 1200);
                else if (x < 300)
                    _acceleration = -(int)(Math.Pow((512 - x), 1.5) / 1200);

                if (!_thumbnailScrolltTimerStarted)
                    _thumbnailScrollTimer.Start();

                _thumbnailScrolltTimerStarted = true;
            }

        }
    }
}

Feel free to send me any comments and feedback, you can also find me on twitter: http://www.twitter.com/fredrikn

Published Friday, September 18, 2009 12:37 PM by Fredrik N
Filed under:

Comments

# Create an automatic scrollable image slider in Silverlight

Wednesday, September 23, 2009 1:31 AM by progg.ru

Thank you for submitting this cool story - Trackback from progg.ru

# This Week???s Silverlight Postings | PHP Scribe

Saturday, September 26, 2009 11:27 AM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Saturday, September 26, 2009 11:51 AM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# Tune Up Your PC &raquo; Post Topic &raquo; This Week???s Silverlight Postings

Pingback from  Tune Up Your PC  &raquo; Post Topic   &raquo; This Week???s Silverlight Postings

# Silverlight相关博客收集20090927

Saturday, September 26, 2009 7:42 PM by geff zhang

收集的silverlight相关文章: Silverlight, SEO

# This Week???s Silverlight Postings | Codedstyle

Saturday, September 26, 2009 8:47 PM by This Week???s Silverlight Postings | Codedstyle

Pingback from  This Week???s Silverlight Postings | Codedstyle

# This Week???s Silverlight Postings | PHP Scribe

Sunday, September 27, 2009 4:45 PM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Sunday, September 27, 2009 4:56 PM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Monday, September 28, 2009 9:59 PM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Monday, September 28, 2009 10:32 PM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Monday, September 28, 2009 10:38 PM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Wednesday, September 30, 2009 3:15 AM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Wednesday, September 30, 2009 3:16 AM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Wednesday, September 30, 2009 3:17 AM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# This Week???s Silverlight Postings | PHP Scribe

Wednesday, September 30, 2009 3:17 AM by This Week???s Silverlight Postings | PHP Scribe

Pingback from  This Week???s Silverlight Postings | PHP Scribe

# re: Create an automatic scrollable image slider in Silverlight

Sunday, January 17, 2010 3:48 PM by Mohamed Soumare

I like the Horizontal Scroll Viewer, but when I tried to implement the Vertical Scroll Viewer it wouldn't work.  Could you please post one example like this that scrolls vertically.

Thanks

# re: Create an automatic scrollable image slider in Silverlight

Tuesday, February 16, 2010 10:44 AM by Amanisti

hey fredrik,,,

i have tried your code and it didn't work in silverlight 3

# re: Create an automatic scrollable image slider in Silverlight

Wednesday, April 21, 2010 8:34 AM by SLCoder

i have tried to implement your code but it didn't worked.....

# re: Create an automatic scrollable image slider in Silverlight

Thursday, June 17, 2010 1:58 PM by John Straumann

Hi:

Any chance you could show how you load the images dynamically?

John.

# re: Create an automatic scrollable image slider in Silverlight

Tuesday, June 29, 2010 4:45 PM by Philip Penning

Worked perfectly thanks.

Leave a Comment

(required) 
(required) 
(optional)
(required)