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

Sorry, comments are closed for this item.