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.