Over a million developers have joined DZone.

A WP7 Databound Graph Control

· Mobile Zone

Visually compose APIs with easy-to-use tooling. Learn how IBM API Connect provides near-universal access to data and services both on-premises and in the cloud, brought to you in partnership with IBM.

For a project we are working on, we needed a simple (and free) WP7 graph usercontrol. The data which the usercontrol visualizes needs to be databound and each time new data arrives, the graph should update itself on-the-fly .In the following tutorial we’ll show how to create such a control from scratch (make note that normally this should also work in Silverlight or WPF projects).

A demo-solution of this tutorial can be downloaded here.

Graph User control: Xaml-code

First, we create a new UserControl. The xaml-part is pretty empty, we’ll add two things:

  1. A style-resource which we’ll use when drawing the graph. In this example, we want the graphlines to have the same color as the accent color of the phone.
  2. An empty gridcontrol in which the graph will be drawn
<UserControl x:Class="GraphControlDemo.GraphControl">

        <Style TargetType="Polyline" x:Key="graphLine">
            <Setter Property="Stroke" Value=
                    "{StaticResource PhoneAccentColor}" />
            <Setter Property="StrokeThickness" Value="2" />

    <Grid x:Name="GraphGrid"  />


If you’d like a more fancy usercontrol, you can add a nice border or any other stuff you’d like. As long as there’s somewhere a gridcontrol named “GraphGrid” everything will be just fine.

Graph User control: Code-behind, overview

The code-behind of our usercontrol has two important parts:

  1. A DrawGraph() method which will…wait for it… draw the graph inside the gridcontrol
  2. A dependency property (DP) containing the collection of values (ints) we want to have a graph drawn of.


public partial class GraphControl : UserControl
        public GraphControl()
            Loaded += (s,e) => DrawGraph();

        public void DrawGraph()

       // GraphValue DependencyProperty

Also notice that we explicitly call the DrawGraph() method once the usercontrol is loaded (line 6). If we don’t do this, our graph want be drawn from the start, even if the dependency property already has a collection bound to it.

Graph User control: Code-behind, drawing the graph

To draw the actual graph, we’ll copy and edit a very straightforward solution by “stoneTip” who answer this StackOverflow question. Make sure to check out the original code on StackOverflow if you need more details about what is actually happening.

We split the DrawGraph() method in two parts: one which will draw the graph, the other part is used if no data was bound to the control which will then simply show ‘No data’ inside the control:
public void DrawGraph()
    if (GraphValues != null && GraphValues.Count(i => true) > 0)
        //Draw graph lines
        GraphGrid.Children.Add(new TextBlock()
                                       Text = "No data", 
                                       VerticalAlignment = VerticalAlignment.Center, 
                                       HorizontalAlignment = HorizontalAlignment.Center

The actual drawing part (inside the if) is as follows:

int maxGraphVal = GraphValues.Max(p => p);
int minGraphVal = GraphValues.Min(p => p);
int gridUnit = 
    (int)GraphGrid.ActualWidth / GraphValues.Count(i => true);
int graphHeight = 
var sparkLine = new Polyline()
                        Style = (Style)Resources["graphLine"]

//Process each value and compute place in graph
int currentX = 0;
decimal graphValRange = maxGraphVal - minGraphVal;
foreach (int graphVal in GraphValues)
    decimal graphY2Val = 
        (graphVal - minGraphVal) / graphValRange;
    double graphY2ValDouble = 
        Convert.ToDouble(graphHeight - (graphY2Val * graphHeight));
    sparkLine.Points.Add(new Point(currentX, graphY2ValDouble));
    currentX += gridUnit;

// Add the spark line to the graph

Graph User control: Code-behind, adding the source data dependency property

Lastly, we need to define a dependency property to which users of our control can bind the graph points. We’ll use an ObservableCollectionfor this (though I’m quite sure that’s not the most lightweight solution):

public ObservableCollection<int> GraphValues
    get { return (ObservableCollection<int>)GetValue(GraphDataProperty); }
    set { SetValue(GraphDataProperty, value); DrawGraph(); }

public static readonly DependencyProperty GraphDataProperty = 
        new PropertyMetadata(null, OnGraphValuesChanged));

 What now only lacks is the part that will automatically update our graph every time new values are added to the collection or the binding changes. This part is inspired on the solution by “Josh G” who answers this SO question.

private static void OnGraphValuesChanged (DependencyObject d, DependencyPropertyChangedEventArgs e)
    GraphControl me = d as GraphControl;
    if (me != null)
        var old = e.OldValue as ObservableCollection<int>;
        if (old != null)
            old.CollectionChanged -= me.OnGraphValueChanged;

        var n = e.NewValue as ObservableCollection<int>;
        if (n != null)
            n.CollectionChanged +=  me.OnGraphValueChanged ;

private void OnGraphValueChanged
    (object sender, NotifyCollectionChangedEventArgs e)

Using the control

With the UserControl ready and waiting. We can now easily add our shiny new ‘GraphControl’ anywhere we like.

First add the namespace to the page on which we want to add the control:


Next, add the control:

<myGraph:GraphControl   GraphValues="{Binding SampleData}"/> 

In the code-behind we now only need to define some ObservableCollectioncalled SampleData which contains the points to be drawn on the graph. For example:

public ObservableCollection<int> SampleData { get; set; }

public MainPage()

    SampleData = new ObservableCollection<int>() { 1, 2, 4 };
    LayoutRoot.DataContext = this;

 To test if the auto-updating works. You could add a button that adds a random sample to the collection every time it is clicked:

private void AddRandSampleBtnClick(object sender, RoutedEventArgs e)
    Random r= new Random();
    SampleData.Add(r.Next(-10, 50));

 And that’s a wrap!

The Mobile Zone is brought to you in partnership with Strongloop and IBM.  Visually compose APIs with easy-to-use tooling. Learn how IBM API Connect provides near-universal access to data and services both on-premises and in the cloud.


Published at DZone with permission of Tim Dams, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}