Lives: 30

Creating Custom DataPoint Popups for Silverlight Chart

Posted Thu Nov 12, 2009 @ 2:40 PM

One of Chart's most powerful features is the ability to define custom templates for data-point popups. 

 

In this post, I will cover defining a basic data-point popup, as well as attaching and displaying more complex data.

 

Start Simple

 

Start with a simple chart:

<ca:Chart x:Name="Chart1" XValue="Area" ChartKind="RoundedBlock" Width="600" Height="400">
<ca:Chart.DataSeries>
<ca:Series YValue="Total" />
</ca:Chart.DataSeries>
</ca:Chart>

In your code-behind, create a simple data class and set your chart's data-source:

public class ChartData
{
public string Area { get; set; }
public double Total { get; set; }
}

void Chart1_Loaded(object sender, RoutedEventArgs e)
{
Chart1.DataSource = new ChartData[]
{
new ChartData() { Area = "North America", Total = 451 },
new ChartData() { Area = "South America", Total = 466 },
new ChartData() { Area = "Europe", Total = 732 },
new ChartData() { Area = "Asia/Pacific", Total = 4088},
new ChartData() { Area = "Africa", Total = 973 }
};
}

If you compile and run your application, you should now have a chart that looks like the following:

 

Define A Custom DataPointPopup

 

You can add a custom data-point popup by first defining it as a resource:

<ca:DataPointPopup x:Key="CustomDataPointPopup">
<ca:DataPointPopup.DataTemplate>
<DataTemplate>
<Border Background="#70000000" CornerRadius="4" Padding="10">
<Grid Width="130">
<Border Background="{Binding DataPoint.Brush}" Opacity="0.6" CornerRadius="3" Margin="-5 -2 -5 -2"/>
<TextBlock Text="{Binding DataPoint.X}" Foreground="White" HorizontalAlignment="Left" FontWeight="Bold" />
<TextBlock Text="{Binding DataPoint.Y}" Foreground="White" HorizontalAlignment="Right" FontWeight="Bold" />
</Grid>
</Border>
</DataTemplate>
</ca:DataPointPopup.DataTemplate>
</ca:DataPointPopup>

And then binding the DataPointPopup property of your series to it:

<ca:Series YValue="Total" DataPointPopup="{StaticResource CustomDataPointPopup}" />

Notice that the template binds to properties of a DataPoint object.  In fact, the DataContext of the popup is an instance of the DataPointContext class.  As well as providing information about the current DataPoint, it also provides information regarding the Series, Chart and more.

 

If you compile and run your application, you should now have a chart that looks like the following:

 

Attaching And Displaying Complex Data

 

If we want to display more advanced information in the popup, we can add additional data to each DataPoint object via its Tag property.  Do this by hooking into the Chart's DataStructureCreated event:

void Chart1_DataStructureCreated(object sender, EventArgs e)
{
Series series = Chart1.DataSeries[0] as Series;
foreach (DataPoint dp in series.DataPoints)
{
switch (dp.X as string)
{
case "North America":
dp.Tag = new ChartData[]
{
new ChartData() { Area = "Canada", Total = 33 },
new ChartData() { Area = "Mexico", Total = 111 },
new ChartData() { Area = "USA", Total = 307 }
};
break;

case "South America":
dp.Tag = new ChartData[]
{
new ChartData() { Area = "Argentina", Total = 40 },
new ChartData() { Area = "Brazil", Total = 191 },
new ChartData() { Area = "Venezuela", Total = 26 },
new ChartData() { Area = "Others", Total = 239 },
};
break;

case "Europe":
dp.Tag = new ChartData[]
{
new ChartData() { Area = "France", Total = 65 },
new ChartData() { Area = "Germany", Total = 82 },
new ChartData() { Area = "UK", Total = 61 },
new ChartData() { Area = "Others", Total = 524 }
};
break;

case "Asia/Pacific":
dp.Tag = new ChartData[]
{
new ChartData() { Area = "China", Total = 1368 },
new ChartData() { Area = "Japan", Total = 127 },
new ChartData() { Area = "India", Total = 1198 },
new ChartData() { Area = "Others", Total = 1395 }
};
break;

case "Africa":
dp.Tag = new ChartData[]
{
new ChartData() { Area = "Egypt", Total = 77 },
new ChartData() { Area = "Morocco", Total = 31 },
new ChartData() { Area = "South Africa", Total = 49 },
new ChartData() { Area = "Others", Total = 816 }
};
break;
}
}
}

Note: Chart.DataStructureCreated is the earliest possible time that you can access the chart's internal data-structures.

 

Now, we can define a more advanced DataPointPopup:

<ca:DataPointPopup x:Key="CustomDataPointPopup">
<ca:DataPointPopup.DataTemplate>
<DataTemplate>
<Border Background="#70000000" CornerRadius="4" Padding="10">
<StackPanel Orientation="Vertical">
<Grid Width="130">
<Border Background="{Binding DataPoint.Brush}" Opacity="0.6" CornerRadius="3" Margin="-5 -2 -5 -2"/>
<TextBlock Text="{Binding DataPoint.X}" Foreground="White" HorizontalAlignment="Left" FontWeight="Bold" />
<TextBlock Text="{Binding DataPoint.Y}" Foreground="White" HorizontalAlignment="Right" FontWeight="Bold" />
</Grid>

<ListBox ItemsSource="{Binding DataPoint.Tag}" Margin="0" Padding="0">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="120" Margin="10 0 0 0">
<TextBlock Text="{Binding Area}" Foreground="White" HorizontalAlignment="Left" />
<TextBlock Text="{Binding Total}" Foreground="White" HorizontalAlignment="Right" FontWeight="Bold" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Grid>
<ItemsPresenter Margin="0" />
</Grid>
</ControlTemplate>
</ListBox.Template>
</ListBox>
</StackPanel>
</Border>
</DataTemplate>
</ca:DataPointPopup.DataTemplate>
</ca:DataPointPopup>

Notice that we can now bind to DataPoint.Tag and use its data to further populate our custom popup.

 

If you compile and run your application, you should now have a chart that looks like the following:

 

Conclusion

 

By defining a custom DataPointPopup template and utilizing DataPoint's Tag property, you can create a custom popup that is able display additional information that is as complex and/or diverse as anything you can imagine!  This is one feature that every developer should give adequate attention to!

 

Posted to Corey Cahill by corey

Posted on Thu Nov 12, 2009 @ 2:40 PM

Filed under: , , , , ,

Comments

There are currently no comments for this blog post.

Anonymous comments are not allowed. Click here to log in or create an account.

Copyright © 2010 ComponentArt, Inc. All rights reserved.