Jarloo

Menu

RumorMill 4 – WPF News Ticker

Updated to .NET4.5. Is now MVVM and uses Caliburn.micro and MahApps metro.

I used to run a few previous web sites. CodeFreezer.com was one of them. While there I wrote RumorMill4. Similar to the v5 I posted here on Jarloo, except the UI layer is considerable different. This version displays the news articles in a ticker similar to a stock ticker.

Download the Source Code

The heart of the display is the Ticker class. This class accepts a class with the news feed information and displays it.

You can view a video of the app here:

The application is quite simple, the most interesting part is the reusable ticker class which can be used to move anything you like across in ticker style, like stock quotes etc…

Here is the XAML code for the Ticker Class:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;

namespace Jarloo.RumorMill4
{
    public class Ticker where T : FrameworkElement
    {
        private readonly DispatcherTimer displayTimer = new DispatcherTimer();

        public EventHandler> ItemDisplayed;

        public bool Running { get; set; }
        public double SeperatorSize { get; set; }
        public TimeSpan Speed { get; set; }
        public Queue Items { get; set; }
        public Panel Container { get; private set; }

        public void Stop()
        {
            displayTimer.Stop();
            Running = false;
        }

        public void Start()
        {
            displayTimer.Start();
            displayTimer.Interval = new TimeSpan(0,0,0,1);
            Running = true;
        }

        public Ticker(Panel container)
        {
            SeperatorSize = 25;

            Container = container;

            Container.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
            Container.Arrange(new Rect(Container.DesiredSize));

            Speed = new TimeSpan(0, 0, 0, 40);

            Items = new Queue();

            displayTimer.Tick += displayTimer_Tick;
            displayTimer.Start();
            Running = true;
        }

        private void displayTimer_Tick(object sender, EventArgs e)
        {
            DisplayNextItem();
        }

        private void DisplayNextItem()
        {
            if (Items.Count == 0) return;

            T item = Items.Dequeue();

            Container.Children.Add(item);

            AnimateMove(item);

            if (ItemDisplayed != null) ItemDisplayed(this, new ItemEventArgs(item));
        }

        private void AnimateMove(FrameworkElement e)
        {
            const double to = -500;

            e.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
            e.Arrange(new Rect(e.DesiredSize));

            double from = Container.ActualWidth;

            int unitsPerSec = Convert.ToInt32(Math.Abs(from - to)/Speed.TotalSeconds);
            int nextFire = Convert.ToInt32((e.ActualWidth + SeperatorSize)/unitsPerSec);

            displayTimer.Stop();
            displayTimer.Interval = new TimeSpan(0, 0, nextFire);
            displayTimer.Start();

            TaggedDoubleAnimation ani = new TaggedDoubleAnimation
                                            {
                                                From = from,
                                                To = to,
                                                Duration = new Duration(Speed),
                                                TargetElement = e
                                            };

            ani.Completed += ani_Completed;

            TranslateTransform trans = new TranslateTransform();
            e.RenderTransform = trans;

            trans.BeginAnimation(TranslateTransform.XProperty, ani, HandoffBehavior.Compose);
        }

        private void ani_Completed(object sender, EventArgs e)
        {
            Clock clock = (Clock) sender;
            TaggedDoubleAnimation ani = (TaggedDoubleAnimation) clock.Timeline;

            FrameworkElement element = ani.TargetElement;
            Container.Children.Remove(element);
        }
    }
}

The rest of the code isn’t very difficult and doesn’t warrent a full walk-through. If your having problems with it please post a comment and I can add additional information here if needed.

Categories:   Code

Comments

  • Posted: January 16, 2012 10:33

    ct

    yay! Thanks for the code :)
  • Posted: January 16, 2012 19:28

    AK

    Thanks! I was looking for this for a long time~
  • Posted: April 13, 2012 01:28

    hhlim

    Hi, which param to adjust the speed? I changed the displayTimer interval and Speed.. seems nothing happened.
    • Posted: April 13, 2012 20:53

      admin

      The speed property in the Ticker's constructor sets a default, but in the example code I am overriding it in the MainWindow's constructor when creating it:
      ticker = new Ticker(LayoutRoot) {Speed = new TimeSpan(0, 2, 0)};
      Just change it to 10 seconds or something and the tickers will travel much faster.
  • Posted: April 24, 2012 12:32

    beowshawitz

    How could you pause it on a mouse enter and then start it again on a mouse leave?
  • Posted: August 2, 2012 00:55

    bjoern

    Thanks fpr the great code. Why can i use the program with a proxy server?
  • Posted: September 2, 2012 19:35

    Tim

    Hi. I was wondering, how do you change the feed that is displayed?
    • Posted: September 2, 2012 22:11

      admin

      There is an XML file that comes with the app that controls what sites the program goes to.
  • Posted: January 29, 2013 08:09

    Eissa

    why dose the text of the items overlap sometime and sometime the separator area is wide
  • Posted: April 12, 2013 07:09

    Fortier

    Hi, First of all thx a lot for this great code. I just have one question, where can i replace the feed by a List of my choice ? Thx u very mutch for ur answer
    • Posted: April 12, 2013 08:56

      Kelly Elias

      There is a feeds.txt file. Just replace the ones listed with your own. One per line.
  • Posted: April 12, 2013 09:19

    Fortier

    Thx , in fact after reading the code i understood that, i 'd like to know if it was possible to display objects which are not rss ? Like i have an object stock with double value, string label and string evolution and i would like to display my List instead of rssfeeds.??? Thank u very mutch for ur answer
    • Posted: April 12, 2013 09:39

      Kelly Elias

      Yes the Ticker class uses generics so you can pass it any object you like and it will handle animating it across the screen. This code uses TickerItem, but you can use whatever you like.
  • Posted: April 14, 2013 08:13

    Fortier

    Sorry to be uch a noob, with all the classes used to catch and parse rss could you tell me just which class i can delete, or which class i have to modify in order to display quote objects public class quote { private string name; private double value; private bool raising; } ? thx a lot in advance
  • Posted: May 7, 2013 09:54

    programmer

    Quick question, How can you stop the scrolling on mouseover?
    • Posted: May 7, 2013 10:27

      Kelly Elias

      I am not sure of a nice way to do so. The problem is that each item is being animated independently instead of one system controlling them all. So to "pause" the animations you would have to loop through each animation.
  • Posted: May 10, 2013 08:27

    DataNerd

    This is great! I have converted this to reading stocks from Yahoo Finance Open Datatables and displaying quotes across the ticker. However, now I would like to get this into more of a MVVM style of architecture. Do you have some advise? I saw your rumor mill 5 post but that does not implement the ticker as you show in this post. Any ideas or thoughts appreciated.
    • Posted: May 10, 2013 13:10

      Kelly Elias

      I took a look at the code and realized it is quite dated. So I modified it to be MVVM. (except for the TickerItem, although I did streamline that) It now uses Caliburn.micro and MahApps metro. Just redownload.
  • Posted: May 10, 2013 13:46

    DataNerd

    Thanks! That really helps put it into better perspective of what a true MVVM. One last thing is have you tried resizing it to a smaller window? When you do the TickerItems from before the resize are overtop of the TickerItems after the resize. You can achieve the same issue if you start, shrink width and then play.
    • Posted: May 10, 2013 13:50

      Kelly Elias

      Yeah I forgot to restrict the window height. Can do that by adding MaxHeight="75" MinHeight="75" in the BaseWindow. I've updated the code as with that as well. As for resizing the width, I am aware of the issue but the problem is not an easy one to fix. Really the way the ticker currently works should be changed. Right now it animates each item individually, while that works it also causes a few issues such as the one you noticed. It also prevents us from adding functionality like the ability to pause all the animation on hover. It should instead have a central controller that animates all the items instead of each of them animating separately.
  • Posted: May 13, 2013 15:21

    DataNerd

    One more thing I have noticed is if you turn the speed up to 15 seconds instead of 2 minutes is that you will get overwriting of the TickerItemViews. Any ideas on correcting that?
  • Posted: May 15, 2013 14:50

    DataNerd

    Curious on your thoughts about how to make the ticker and ticker item classes more mvvm friendly. I have had some ideas but all have been failed attempts. Thanks in advance. Keep up the good work.
    • Posted: May 15, 2013 16:21

      Kelly Elias

      I wrote this project initially about 6 years ago, and had no idea what MVVM was. I did the easy work to refresh it to be more MVVM friendly but as you state those two things are not very MVVM friendly. I don't have any easy answers to fixing this while keeping the implementation light-weight. (you don't want a viewmodel for each item, but more like a single viewmodel with a collection of views being displayed in the ticker)
  • Posted: May 20, 2013 09:38

    DataNerd

    Ok sounds good. I wasn't sure if you had something in the works already to make it more MVVM friendly or if you had any insight. But event though this is an older application that you have made and shared with us, it is still very helpful. It has helped me learn a great deal about Caliburn.Micro and as well how to formulate a ticker type of visualization. A very much needed part in my application that I am building. Thanks for all that you have done. Keep up the good works!
  • Posted: August 24, 2013 01:09

    JLSF

    Hello, looks reaaly good do you think this can be used as a Silvelight application, (MEF Module)? Thanks
  • Posted: October 15, 2013 09:16

    Nemesis

    I was wondering how it might be possible to incorporate this into an existing app project. I have an interactive map that I want to have a Twitter feed ticker on the top. But whenever I do myTicker = new Ticker(); nothing happens. How is it setup exactly and how can I go about incorporating something like this in my own? I thought maybe the MVVM update would allow Blend Expression to pick up on it as an element but it doesnt.
  • Posted: May 15, 2014 15:32

    Kjetil

    Thanks for this brilliant code! I converted to vb and used as basis for a ticker. Using higher speed and larger fonts though, the news items started to overlap. I realized the next fire timer needed more precision and adjusted these calculations to include milliseconds. Sharing it back here, in case someone should run into the same issue. Dim unitsPerSec As Double = Math.Abs(from - [to]) / Speed.TotalSeconds Dim nextFire As Double = (e.ActualWidth + SeperatorSize) / unitsPerSec Dim nextFireSec As Integer = Convert.ToInt32(Math.Floor(Convert.ToDecimal(nextFire))) Dim nextFireMillis As Integer = Convert.ToInt32(Math.Floor(((nextFire - nextFireSec) * 1000))) displayTimer.Stop() displayTimer.Interval = New TimeSpan(0, 0, 0, nextFireSec, nextFireMillis)
  • Posted: August 14, 2015 04:52

    Surreal

    Thanks for the code. Existing Vb project? More difficult to traslate...
    • Posted: August 19, 2015 11:20

      Kelly Elias

      No sorry I haven't programmed in VB for over 10 years now and don't have a VB version available.
  • Posted: August 14, 2015 04:56

    Surreal

    Good morning, how can you put a repeater automatically? Thanks ... sorry my english
  • Posted: November 12, 2015 04:30

    Michele Mura

    Thanks for the code! But is there also a .net 4.0 version?