Tuesday, February 19, 2008

Do Your Free WPF Line Chart Yourself


There are some free WPF charting controls around the web but, sometimes what you get is a limited version of something that soon will not be free, that's why develop your own controls is a great idea and thanks to WPF is not so difficult.


In order to do this we will use the Polyline class and a ItemsControl to draw the grid lines.


XAML:


<Window x:Class="PolylineTest.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Polyline Test" Height="700" Width="700">

<Viewbox Stretch="Fill">

<Grid x:Name="myGrid">

<ItemsControl x:Name="itemsControl" ItemsSource="{Binding}">

<ItemsControl.ItemsPanel>

<ItemsPanelTemplate>

<StackPanel IsItemsHost="True" Orientation="Horizontal"/>

</ItemsPanelTemplate>

</ItemsControl.ItemsPanel>

<ItemsControl.ItemTemplate>

<DataTemplate>

<Border BorderBrush="LightGray" BorderThickness="0.1" Width="10" Loaded="Border_Loaded"/>

</DataTemplate>

</ItemsControl.ItemTemplate>

</ItemsControl>

</Grid>

</Viewbox>

</Window>


Code Behind:


using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;


using System.Windows.Threading;

using System.Collections.ObjectModel;


namespace PolylineTest

{

/// <summary>

/// Interaction logic for Window1.xaml

/// </summary>

public partial class Window1 : Window

{

Polyline myPolyline;

DispatcherTimer timer = new DispatcherTimer();

Random gen = new Random(DateTime.Now.Millisecond);

int x = 0;

int step = 10;

ObservableCollection<Point> points = new ObservableCollection<Point>();


public Window1()

{

InitializeComponent();


myPolyline = new Polyline();

myPolyline.Stroke = System.Windows.Media.Brushes.SlateGray;

myPolyline.StrokeThickness = 1;

myPolyline.FillRule = FillRule.EvenOdd;


myGrid.Children.Add(myPolyline);


timer.Interval = TimeSpan.FromMilliseconds(500);

timer.Tick += new EventHandler(timer_Tick);

timer.Start();


this.DataContext = points;

}


private void timer_Tick(object sender, EventArgs e)

{

Point point = new Point(x, gen.Next(1000));

x += step;

points.Add(point);

}


private void Border_Loaded(object sender, RoutedEventArgs e)

{

Point point = (Point)(sender as Border).DataContext;

myPolyline.Points.Add(point);

}

}

}


Every 0.5 seconds an item is added to the source of the ItemsControl and then a Border is created, just after that we take the Point within the DataContext of the Border and add it to the Polyline. Easy! :)


Please, if this is helpful leave your comment. If there are any questions just fire away!

FeR.

2 comments:

Unknown said...

Your post has been really helpful. I am trying to draw some charts, and this gave me good insight. Thanks. I have the basic graph down, but I am still struggling with how to make my graph scalable like yours. Can you explain :

Point point = (Point)(sender as Border).DataContext;

How does this work?

WPF Charts said...

Happy to see posts about drawing charts, this really helps inexperienced WPF Charts developers!