Silverlight Charts: Coordinates on Mousemove

In this article we see how we get the coordinates in Silverlight charts on mouse move. It's a bit tricky, but it worked great for me.



Most of us might be familiar with visifire charts. The most interesting feature of these charts is the coordinates shown during mouse over.

In this article we see how we get the coordinates in Silverlight charts on mouse move. It's a bit tricky, but it worked great for me.

Basic Bar Chart

Creating a Bar chart: 


Let's start from a basic Bar Chart: 
 
The xaml code below will generate a basic bar chart.

  
<Grid x:Name="LayoutRoot" Background="White">
        <charting:Chart x:Name="BarChartSample" >
            <charting:Chart.Series>
                <charting:ColumnSeries IndependentValueBinding="{Binding Key}"
                           DependentValueBinding="{Binding Value}"
                           ItemsSource="{Binding}"/>
            </charting:Chart.Series>
            <charting:Chart.Axes>
                <charting:CategoryAxis Orientation="Horizontal" />
                <charting:LinearAxis Orientation="Vertical" />
            </charting:Chart.Axes>
        </charting:Chart>

The C# code below loads data in the chart:

void
SilverlightControl11_Loaded(object sender, RoutedEventArgs e)
{
    BarChartSample.DataContext = new KeyValuePair<string, int>[]
            {
                new KeyValuePair<string, int>("One", 1),
                new KeyValuePair<string, int>("Two", 2),
                new KeyValuePair<string, int>("Three", 3),
                new KeyValuePair<string, int>("Four", 4)
            };
 }

The code above just fills in the column series with some data.

Specifying Axes:

Implicitly specifying the axes for the chart is highlighted in the xaml code below.

<
charting:Chart x:Name="BarChartSample" >
    <charting:Chart.Series>
        <charting:ColumnSeries IndependentValueBinding="{Binding Key}"
                   DependentValueBinding="{Binding Value}"
                   ItemsSource="{Binding}"/>
    </charting:Chart.Series>
    <charting:Chart.Axes>
        <charting:CategoryAxis Orientation="Horizontal" />
        <charting:LinearAxis Orientation="Vertical" />
    </charting:Chart.Axes>
</charting:Chart>

It is not mandatory to provide the axis. If not provided the chart generates its own axes.

When we specify the axes CategoryAxis is the axis that's going to show the string and the LinearAxis will show the numbers from 1-4.

Chart showing coordinates on mouseover

To implement the mouse move event let us capture the mouse event from the series itself.

Then the xaml will look like:

<
charting:Chart x:Name="BarChartSample" >
    <charting:Chart.Series>
        <charting:ColumnSeries IndependentValueBinding="{Binding Key}"
                   DependentValueBinding="{Binding Value}"
                   ItemsSource="{Binding}"
                   MouseMove="SampleSeries_MouseMove"
                   />
    </charting:Chart.Series>
    <charting:Chart.Axes>
        <charting:CategoryAxis Orientation="Horizontal" />
        <charting:LinearAxis Orientation="Vertical" />
    </charting:Chart.Axes>
</charting:Chart>

Implementation of mouse move event
 
Implementation of the mousemove event is very interesting and tricky

Get the position of mouse

e.GetPosition provides the position (x,y) in relation to this Series (x,y) axis. 

void
SampleSeries_MouseMove(object sender, MouseEventArgs e)
{
   Point coordinate = e.GetPosition((Series)BarChartSample.Series[0]);
}

Get the axes

Here we come across why we added the axes implicitly.

We get the Axes themselves which we previously declared n the interface variable of the corresponding axes. 

void
SampleSeries_MouseMove(object sender, MouseEventArgs e)
{
    Point coordinate = e.GetPosition((Series)BarChartSample.Series[0]);
    ICategoryAxis xAxis = (CategoryAxis)BarChartSample.Axes[0];
    IRangeAxis yAxis = (LinearAxis)BarChartSample.Axes[1];
}

Note that the Axes are converted to interfaces and not the concrete classes

Get point of intersections

Now, let us find the point of intersection from the mouse position and axes

void
SampleSeries_MouseMove(object sender, MouseEventArgs e)
{
    Point coordinate = e.GetPosition((Series)BarChartSample.Series[0]);
    ICategoryAxis xAxis = (CategoryAxis)BarChartSample.Axes[0];
    IRangeAxis yAxis = (LinearAxis)BarChartSample.Axes[1];
    // two methods from the Axis interfaces provides the points of intersection between the 
    mouse position (X,Y) position in relation to each Axis
    var xHit = xAxis.GetCategoryAtPlotAreaCoordinate(coordinate.X);
    var yHit = yAxis.GetPlotAreaCoordinateValueRange(coordinate.Y);
    // on getting a result print it out to the "Output window". 
    if (xHit != null) 
        Debug.WriteLine("Hit X axis on {0}", xHit.ToString());
    if (yHit.HasData)
        Debug.WriteLine("Hit Y axis on ({0}, {1})", yHit.Minimum, yHit.Maximum);
}

Now we get the intersection points.

This can be displayed by any kind of styling or in a rectangle etc. according to the requirement

Conclusion 

This article provides an extra feature for the charts, displaying coordinates on mouse over.

This only gives an idea on how it can be done. The coordinates can be displayed in any style as per the requirement. I expect that this will help the readers. 

Happy Coding! 

Let the adventure of silverlight keep on going.