Click here to Skip to main content
13,831,409 members
Click here to Skip to main content
Add your own
alternative version

Stats

20.8K views
7 bookmarked
Posted 20 May 2011
Licenced CPOL

WPF/Silverlight Content Ticker/News Ticker Control

, 20 May 2011
Rate this:
Please Sign up or sign in to vote.
The ContentTicker control is a generic control that can be used to slide content.

WPF includes the Canvas control that allows you to place elements using exact coordinates.

To position an element on the Canvas, you set the attached Canvas.Left and Canvas.Top properties. Canvas.Left sets the number of units between the left edge of your element and the left edge of the Canvas. Canvas.Top sets the number of units between the top of your element and the top of the Canvas.

Although the Canvas control has a definite visible area determined by the Height and Width properties of the control, it allows child controls to be virtually placed at any coordinate. We can use this particular feature of the Canvas control to achieve a ticking/sliding effect by continuously changing the coordinates of the content.

Demo application screenshot

The ContentTicker control derives from the WPF ContentControl. The ControlTemplate is defined to place the content in a Canvas control. Also, a double animation is defined that is started on loading of the control. The animation target property is set to the attached property (Canvas.Left) of the content.

public class ContentTicker : ContentControl
{
    Storyboard _ContentTickerStoryboard = null;
    Canvas _ContentControl = null;
    ContentPresenter _Content = null;

    static ContentTicker()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ContentTicker), 
           new FrameworkPropertyMetadata(typeof(ContentTicker)));
    }

    public ContentTicker()
    {
        this.Loaded += new RoutedEventHandler(ContentTicker_Loaded);
    }

    ..
}
<controltemplate targettype="{x:Type local:ContentTicker}">
  <canvas x:name="PART_ContentControl" width="300" 

        verticalalignment="Stretch" 

        horizontalalignment="Stretch" height="150" 

        removed="{TemplateBinding Background}">
    <canvas.triggers>
      <eventtrigger routedevent="Canvas.Loaded">
        <beginstoryboard>
          <storyboard x:name="ContentTickerStoryboard" storyboard.targetproperty="(Canvas.Left)">
            <doubleanimation storyboard.targetname="PART_Content" repeatbehavior="Forever">
            </doubleanimation>
          </storyboard>
        </beginstoryboard>
      </eventtrigger>
    </canvas.triggers>
    <contentpresenter x:name="PART_Content" 

      verticalalignment="{TemplateBinding ContentControl.VerticalAlignment}" 

      horizontalalignment="{TemplateBinding ContentControl.HorizontalAlignment}" 

      contenttemplate="{TemplateBinding ContentControl.ContentTemplate}" 

      content="{TemplateBinding ContentControl.Content}">
    </contentpresenter>
  </canvas>
</controltemplate>

The ContentTicker control defines two additional dependency properties for defining the rate (speed) of ticking and direction (east or west). The rate is used to calculate the duration of the animation, the time required to complete one cycle of the animation.

public double Rate
{
    get { return (double)GetValue(RateProperty); }
    set { SetValue(RateProperty, value); }
}

public static readonly DependencyProperty RateProperty =
    DependencyProperty.Register("Rate", typeof(double), 
    typeof(ContentTicker), new UIPropertyMetadata(60.0));

public TickerDirection Direction
{
    get { return (TickerDirection)GetValue(DirectionProperty); }
    set { SetValue(DirectionProperty, value); }
}

public static readonly DependencyProperty DirectionProperty =
    DependencyProperty.Register("Direction", 
    typeof(TickerDirection), typeof(ContentTicker), 
    new UIPropertyMetadata(TickerDirection.West));

The canvas size is adjusted while loading the control and Content is vertically aligned in the canvas according to the user specified settings. Further, the animation parameters are adjusted according to the width of the Canvas and Content controls.

The animation is dependent on the width of the Canvas and Content so the animation details are updated every time the size of these are changed.

void UpdateAnimationDetails(double holderLength, double contentLength)
{
    DoubleAnimation animation = 
        _ContentTickerStoryboard.Children.First() as DoubleAnimation;
    if (animation != null)
    {
        bool start = false;
        if (IsStarted)
        {
            Stop();
            start = true;
        }

        double from = 0, to = 0, time = 0;
        switch (Direction)
        {
            case TickerDirection.West:
                from = holderLength;
                to = -1 * contentLength;
                time = from / Rate;
                break;
            case TickerDirection.East:
                from = -1 * contentLength;
                to = holderLength;
                time = to / Rate;
                break;
        }

        animation.From = from;
        animation.To = to;
        TimeSpan newDuration = TimeSpan.FromSeconds(time);
        animation.Duration = new Duration(newDuration);

        if (start)
        {
            TimeSpan? oldDuration = null;
            if (animation.Duration.HasTimeSpan)
                oldDuration = animation.Duration.TimeSpan;
            TimeSpan? currentTime = 
               _ContentTickerStoryboard.GetCurrentTime(_ContentControl);
            int? iteration = 
               _ContentTickerStoryboard.GetCurrentIteration(_ContentControl);
            TimeSpan? offset = 
                TimeSpan.FromSeconds(
                currentTime.HasValue ? 
                currentTime.Value.TotalSeconds % 
                  (oldDuration.HasValue ? oldDuration.Value.TotalSeconds : 1.0) : 
                0.0);
            
            Start();

            if (offset.HasValue &&
                offset.Value != TimeSpan.Zero &&
                offset.Value < newDuration)
                _ContentTickerStoryboard.SeekAlignedToLastTick(
                  _ContentControl, offset.Value, TimeSeekOrigin.BeginTime);
        }
    }
}

The ContentTicker control is a generic control to slide the content. It can be used as a news ticker, thumbnails slider, RSS feed slider, etc., depending on the requirement. The Start/Stop and Pause/Resume methods can be used to dynamically change the behavior of the sliding content.

The demo application uses the control as a text ticker and provides the interfaces to change the speed, content, and direction at run time.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Koder Hack
Software Developer TRG Tech
Pakistan Pakistan
No Biography provided

You may also be interested in...

Pro

Comments and Discussions

 
GeneralAlternate approach Pin
Schnizit24-Jan-12 3:12
memberSchnizit24-Jan-12 3:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190114.1 | Last Updated 20 May 2011
Article Copyright 2011 by Koder Hack
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid