Bubbles – 1 Chart – three Axes

 

In this follow up to yesterday’s blog post about the Bubbles Chart available from the December Release of the Silverlight Toolkit, I’d like to explore the unique advantages the bubbles chart provides for finding outliers in many real world situations.

The scenario I’m contriving is this: I’d like to examine two vital sets of (fictional) information at once

  • How many blog blog posts and videos have we created on each of 8 important topics
  • On average, how interested are our members in each of these topics.

I could create two charts and compare them side by side, but a bubbles chart instantly identifies where I have problems and where I’m on track…

ThreeWayFullView

In this chart, the larger the bubble the greater the average user interest, on a scale of 0 to 100.  The Y axis (on the left side) is the number of blog entries and videos on the topic (the negative numbers are an artifact of accommodating a large bubble that falls below zero), the X axis lists the 9 topics (at the moment, the bubbles chart can only place integers and dates, so my Topics class uses an ID and a lookup, explained below. Clicking on a bubble causes its information to be displayed above.

The bubble I’ve clicked on in the image above is number 5 (Skinning) and it is indicating we’ve got it about right, the interest level is 60 out of 100, and we’ve done 125 posts which is tracking appropriately.  In the cropped image below I focus on two outliers,

ThreeWayBubbles

The tiny bubble up at 350 indicates that we have a topic of little interest that we are spending too much time on, and the giant bubble down around 0 (actually indicating 5 posts) is a sure sign we have a high interest topic that we’re ignoring. An equal sized bubble up and to the right shows a high interest topic we are covering well.

Key here is that at a glance we’ve identified two problems that are easily missed without this chart, and easily solved with this information.

How It Works

 

 

The implementation is very much as you saw yesterday. To get to the heart of it, I created a single page version that has only  the following files:

  • Page.xaml
  • Page.xaml.cs
  • App.xaml
  • App.xaml.cs
  • BlogTopic.cs

The App.xaml files. Page.Xaml is posted, here is an excerpt that illustrates the important points…

  <Grid
    x:Name=”Layout”
    Background=”White”>
    <Grid.RowDefinitions>
      //….
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
       //….
   </Grid.ColumnDefinitions>
    <Border  //….  />
    <TextBlock
      x:Name=”Message” //… />
    <charting:Chart
      x:Name=”DrillDownChart”
      BorderBrush=”Gray”
      Margin=”1″
      Grid.Row=”1″
      Grid.ColumnSpan=”3″>
      <charting:Chart.Series>
        <charting:BubbleSeries
          Title=”.”
         IndependentValueBinding=”{Binding TopicID}”
          DependentValueBinding=”{Binding NumberOfPosts}”
          SizeValueBinding=”{Binding AverageRating}” />

      </charting:Chart.Series>
    </charting:Chart>
  </Grid>
</UserControl>

The three lines that matter are the binding of the Independent and Dependent values and the SizeValue. These are bound to properties of the BlogTopic class which, as you’ve seen with other classes, both defines its members and defines a static method to generate the data we’ll need.

In this case, since I need to provide integers for the IndependentValueBinding, I provide a TopicID as an integer, and a static Dictionary that maps these integers to strings (e.g., TopicID 2 = Web Services.  The complete listing for BlogTopic.cs  is posted, here is an excerpt,

namespace Bubbles3D
{
  public class BlogTopic
  {
   public static Dictionary<int, string> Topics =
          new Dictionary<int, string>();

    public int TopicID { get; set; }
    public int NumberOfPosts { get; set; }
    public double AverageRating { get; set; }

    public static List<BlogTopic> CreateData()
    {
      Topics.Add( 1, “Toolkit” );
      Topics.Add( 2, “Web Services” );
       //….

      List<BlogTopic> BlogTopics = new List<BlogTopic>();

      BlogTopics.Add(
        new BlogTopic() {
              TopicID = 1,
            NumberOfPosts = 250,
            AverageRating = 65 } );
             //….
      return BlogTopics;
    }

Finally, the only remaining code is in the Page.xaml.cs where the ItemSource must be attached to the bubble series and the Selection changed event must be handled.  Here is that code in full,

using System.Windows.Controls;
using System.Collections.Generic;
using System.Windows;

using Microsoft.Windows.Controls.DataVisualization.Charting;
namespace Bubbles3D
{
  public partial class Page : UserControl
  {
    private List<BlogTopic> blogTopics;
    public Page()
    {
      InitializeComponent();
      Loaded += 
          new System.Windows.RoutedEventHandler( Page_Loaded );
    }

    void Page_Loaded( 
          object sender, System.Windows.RoutedEventArgs e )
    {
      BubbleSeries bSeries = 
             DrillDownChart.Series[0] as BubbleSeries;
      blogTopics = BlogTopic.CreateData();
      bSeries.ItemsSource = blogTopics;
      bSeries.IsSelectionEnabled = true;
      bSeries.SelectionChanged += 
           new SelectionChangedEventHandler( bSeries_SelectionChanged );
      Message.Text = 
          "Larger bubbles are more popular, higher bubbles are are topics with more articles";
    }

    void bSeries_SelectionChanged( 
      object sender, SelectionChangedEventArgs e )
    {
      if ( e.AddedItems.Count > 0 )
      {
        BlogTopic blogTopic = e.AddedItems[0] as BlogTopic;
        Layout.DataContext = blogTopic;
        Message.Text = blogTopic.NumberOfPosts.ToString() + 
             " posts on " + 
              BlogTopic.Topics[blogTopic.TopicID] + 
              " with an average interest of  " + 
              blogTopic.AverageRating.ToString() + 
              " on a scale of 0 to 100";
      }
    }
  }
}
 
Source: Bubbles3D.zip

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in z Silverlight Archives. Bookmark the permalink.