Silverlight charts, and reaching my inner child

So, there was a question in the Code Project forums today from somebody looking to create an application that uses input data, LINQ and charting. My first reaction was, “we don’t provide code for people; it’s not rentacoder”, but I took pity on the poor so and so. To that end, I decided to knock together a quick sample for him that hopefully will get the point across to him. Here’s the code in all it’s glory.

First of all, here’s a quick class that I’m going to use to simulate the database table:

using System;

namespace GraphingSample
{
  public class LinqDataSample
  {
    public string Name { get; set; }
    public int Value { get; set; }
  }
}

Hey, I’m not going to do all the hard work and create the whole solution.;->

Here’s the source for the control:

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.Collections.ObjectModel;

namespace GraphingSample
{
  public partial class MainPage : UserControl
  {
    private ObservableCollection<LinqDataSample> _data = new ObservableCollection<LinqDataSample>();
    public MainPage()
    {
      InitializeComponent();

      AddData(10, "Josh");
      AddData(20, "Colin");
      AddData(15, "Karl");
      AddData(33, "Sacha");
      AddData(24, "Bill");
      AddData(39, "Daniel");
      AddData(14, "Corrado");
      AddData(22, "Marlon");
      AddData(24, "Laurent");

      DataContext = Data;
    }

    public ObservableCollection<LinqDataSample> Data
    {
      get
      {
        return _data;
      }
      set
      {
        _data = value;
      }
    }

    private void AddData(int value, string name)
    {
      _data.Add(new LinqDataSample() { Name = name, Value = value });
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
      int value = 0;
      string name = txtName.Text;
      if (!string.IsNullOrEmpty(name))
      {
        if (int.TryParse(txtValue.Text, out value))
        {
          _data.Add(new LinqDataSample() { Name = name, Value = value });
        }
      }
    }
  }
}

Let’s break this code down. We create an ObservableCollection, which we’d normally fill using LINQ to retrieve data from the database. The DataContext allows the XAML to bind to the collection. In the button click method, we are going to update the observable collection with values that the user enters in on the control (we’d normally update the database at this point too). If you’re not too aware of how Silverlight and WPF works, then the instant update to the chart because of the ObservableCollection is awesome.

<UserControl
  x:Class="GraphingSample.MainPage"
  xmlns="<a href="http://schemas.microsoft.com/winfx/2006/xaml/presentation">http://schemas.microsoft.com/winfx/2006/xaml/presentation</a>"
  xmlns:chart="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
  xmlns:d="<a href="http://schemas.microsoft.com/expression/blend/2008">http://schemas.microsoft.com/expression/blend/2008</a>"
  xmlns:mc="<a href="http://schemas.openxmlformats.org/markup-compatibility/2006">http://schemas.openxmlformats.org/markup-compatibility/2006</a>"
  xmlns:x="<a href="http://schemas.microsoft.com/winfx/2006/xaml">http://schemas.microsoft.com/winfx/2006/xaml</a>"
  d:DesignHeight="480"
  d:DesignWidth="640"
  mc:Ignorable="d">
  <Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
      <RowDefinition Height="20"/>
      <RowDefinition Height="20"/>
      <RowDefinition Height="20"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="30"/>
      <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Grid.Row="0" Text="Name"/>
    <TextBlock Grid.Column="0" Grid.Row="1" Text="Value"/>
    <TextBox x:Name="txtName" Grid.Column="1" Grid.Row="0"/>
    <TextBox x:Name="txtValue" Grid.Column="1" Grid.Row="1"/>
    <Button
      Grid.Column="1"
      Grid.Row="2"
      HorizontalAlignment="Right"
      Click="Button_Click"
      Content="Add"/>
    <chart:Chart Grid.ColumnSpan="2" Grid.Row="3">
      <chart:Chart.Series>
        <chart:PieSeries
          DependentValuePath="Value"
          IndependentValuePath="Name"
          IsSelectionEnabled="True"
          ItemsSource="{Binding}"
          Title="Sample"/>
      </chart:Chart.Series>
    </chart:Chart>
  </Grid>
</UserControl>

The DependentValuePath ties back to the numeric value in the class, and the IndependentValuePath ties up to the name property from our data class. Because we set the ItemsSource to {Binding}, we basically set our item source to pick up the data from the DataContext that we set up in the UserControl.

I will say, at this point, that I normally wouldn’t write my code exactly like this – I’m a big proponent of MVVM, but this is a sample aimed at helping somebody who’s new to Silverlight. Take it from me – this stuff is even cooler with MVVM; if you haven’t explored it yet, you really owe it to yourself.

That’s it – it’s really easy to do, and Silverlight updating means that it’s incredibly good fun. There you go burger87, this one’s for you.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s