How to display custom tool tips in Silverlight Charts?

by Naveen 3. March 2010 11:49
custom tool tip in silverlight charts

Download Sample Projects (28.22 kb)

In my previous post, How to set silverlight column chart style programatically", I discussed one of the customizations of chart styles. In this post I will discuss one more customization of Silverlight charts rendering. This is about customizing display of Tooltip display on charts. If you look at default tool tip display, they are limited to displaying some combination of Independent and Dependent value. In some cases, that information is sufficient. But you may have cases where you want your tool tips to be verbose to convey more information about the data point that was used to render that point or column etc.

Template is the key

First and foremost concept that you will need to understand is how a chart actually gets rendered. Who decided the layout of various components of a chart display. Like any other Silverlight control, its the control template that defines how to chart is going to be rendered. So to customize the dispplay of Silverlight control, you can create a new template or take the default template and make modifications to it to come up with your own display scheme. Now you are asking from where can you get the default template for various chart types. The answer to it is Silverlight Toolkit source code. If you look in Charting/DataPoint folder of Controls.DataVisualization.Toolkit project, you will find template files for all chart types.

Customize Tooltip For Chart

Let us get started. For this discussion I picked Column type chart. Here are the steps that I followed to create a new template file for my column charts.

  • Add a new resource dictionary file in your project. In sample project I added ColumnChartStyle.xaml file under Assets folder.
  • Open ColumnDataPoint.xaml file from DataPoint folder from tool kit source. Copy the content of this file into your resource file.
  • Make sure that you change the build action of your resource file to Resource from Page
  • Assign a key to your style as shown below. You can pick any unique name. You are going to use the key when we apply this new template and style to our column charts.
    
    <Style TargetType="charting:ColumnDataPoint" x:Key="ByteBlocksColumns">
    
    
  • Open the XAML file where you have added chart that you want to display. In the sample project, it is in Home.xaml. And then assign DataPointStyle property to point to the static resource that we created from default implementation of ColumnDataPoint. And make sure that you use the key name that you used in the resource file. Following snippet shows how I did it in sample project.

    
    <chartingToolkit:Chart Title="Fruit Supply and Demand" 
       x:Name="FruitChart" 
       Width="500" 
       Height="350">
     <chartingToolkit:Chart.Series>
      <chartingToolkit:ColumnSeries
    		DataPointStyle="{StaticResource ByteBlocksColumns}"
            Title="Fruit Supply"
            IndependentValueBinding="{Binding Name}"
            DependentValueBinding="{Binding Supply}"/>
      </chartingToolkit:Chart.Series>
    </chartingToolkit:Chart>
    
    

Now you should be able to compile and run your project. We have not done any customization of tool tip yet. At this point you should be able to run the project with default template.

TooltipService and Tooltip

If you look near bottom of ColumnChartStyle.xaml file, you will find following snippet of code.


<ToolTipService.ToolTip>
 <ContentControl Content="{TemplateBinding FormattedDependentValue}"/>
</ToolTipService.ToolTip>

This is default implementation of how and what is displayed in tool tip. So you can see that by default only DependentValue is displayed. So this is the place where you will need to make changes to customize the display of tooltip for chart. If you are only interested in making some minor changes like adding some static text or adding display of dependent value as well, you can make a change as below.


<ToolTipService.ToolTip>
 <StackPanel Orientation="Horizonal">
 <ContentControl Content="{TemplateBinding FormattedDependentValue}"/>
 <TextBlock Text="-" />
  <ContentControl Content="{TemplateBinding FormattedIndependentValue}"/>
 </StackPanel Orientation="Horizonal">
</ToolTipService.ToolTip>

Customizing Tooltip Display at run time

In the sample project, I have implemented a use case where I want to create tool tip display at run time. What this means is that content of tool tip is being constructed based on some input from the existing data that is bound to that column. So in the template I am going to make some changes as shown below.


<ToolTipService.ToolTip>
<StackPanel Orientation="Horizontal">
<ContentControl Content="{Binding Id, Converter={StaticResource FruitConverter}}"/>
</StackPanel>
</ToolTipService.ToolTip>

In the snippet above you will see use of two things. One is that I am binding the content to the actual data object that was used to render that point. Second is use of converter. I am passing "Id" of the object as parameter to the converter. And in the converter I do some mock query to get more data. Following code shows how I constructed text of tool tip.


public class FruitSupplyToolTipConverter : IValueConverter
{
 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 {
  return GetToolTip(int.Parse(value.ToString()));
 }

 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 {
  return value;
 }

 object GetToolTip(int id)
 {
  var supply = MockData.FruitSupply.GetSupply();
  var query = from item in supply where item.Id == id select item;
  var items = query.ToList();
  if (items.Count == 0)
  {
   return string.Empty;
  }
  return CreateToolTip(items[0]);
 }

 object CreateToolTip(FruitSupply supply)
 {
  var panel = new StackPanel();
  panel.Orientation = Orientation.Vertical;
  var tipTextBlock = new TextBlock();
  tipTextBlock.Inlines.Add(new Run { Text = supply.Name });
  tipTextBlock.Inlines.Add(new LineBreak());
  tipTextBlock.Inlines.Add(new Run { Text = string.Format("Supply: {0}", supply.Supply)});
  tipTextBlock.Inlines.Add(new LineBreak());
  panel.Children.Add(tipTextBlock);
  var hlink = new HyperlinkButton();
  hlink.Content = "For more informattion Goto http://www.ByteBlocks.com";
  hlink.NavigateUri = new Uri("http://www.byteblocks.com");
  panel.Children.Add(hlink);
  return panel;
  }
}

You could argue that instead of going to the extent of using converter to build a tool tip text, I could have added another property to data object that contains the text and then bind tool tip to that property. That would have worked perfectly as well. But for demonstrating how you can construct tool tip text based on some other pieces of data or if tool tip content changes rapidly with time as well, then you need to access it at run time.

I hope this should give you good starting point to go nuts on more nifty tool tips.

Give your advice to big bosses and make money

Views: 2728

Tags: , ,

Charting | Silverlight

How to set axis properties programatically for Silverlight charts

by Naveen 7. December 2009 06:23

In my previous post How to hide gridlines in charts, I showed how you can accomplish the task from XAML. This is all good when you know that rendering behavior of you chart is not going to change or you do not have to modify the display at run time based on some computed values curing run time. And works great for design time as well. But a lot of time you want to change the behavior at run time. In that case you need to know how you can change properties of axis programatically.

Each chart has a collection of Axis. By default this collection is empty. Charting controll fills this collection if you do not provide any. And it makes it decision based on the type of values you render on these axis. For example tf you are displaying DateTime type values on an axis, control will add DateTimeAxis to its collection. I have two liner axis in my chart that display simple numeric values. Following code shows how I added two linear axis, X and Y, to my chart. Most important property to set is Orientation. Without it, rendering engine does not know what axis you intend to change.


private void SetYAxis()
{
  var lax = new LinearAxis();
  lax.ShowGridLines = false;
  lax.Orientation = AxisOrientation.Y;
  lax.Title = "Response Time";
  myChart.Axes.Add(lax);
}

private void SetXAxis()
{
   var lax = new LinearAxis()
              {
                ShowGridLines = false,
                Title = "Interval",
                FontWeight = FontWeights.Bold,
                MaxHeight = 1,
                Opacity = 0,
                Orientation = AxisOrientation.X
               };
   myChart.Axes.Add(lax);
}

Give your advice to big bosses and make money

Views: 1906

Tags: , ,

Silverlight | Charting

How to hide grid lines in Silverlight chart?

by Naveen 7. December 2009 05:53

This is one of the thing that is easy to do but no so obvious. I think mostly its lack of complete description of how charting controls provided in Silverlight toolkit work and how to manipulate them. When you draw charts like Line, Column, Bar etc., the grid line on DependentValue are rendered by default. There is a property ShowGridLines available on DisplayAxis class that is base class for axis. You just need to set its value to False. For example in my line chart I did not want to show grid lines on grid lines on Y axis. Following XAML snippets shows how I turned off rendering of grid lines on Y-axis.


<chartingToolkit:Chart Title="Latency" x:Name="latencyChart" BorderThickness="1">
 <chartingToolkit:Chart.Series>
  <chartingToolkit:LineSeries Title="Val 1" 
     DependentValueBinding="{Binding Threshold}"
     IndependentValueBinding="{Binding IndependentValue}" 
     AnimationSequence="Simultaneous" />
  <chartingToolkit:LineSeries Title="Val 2Latency" 
   DependentValueBinding="{Binding Current}" 
   IndependentValueBinding="{Binding IndependentValue}" 
   AnimationSequence="Simultaneous" />
  <chartingToolkit:LineSeries Title="Val 3" 
   DependentValueBinding="{Binding Average}" 
   IndependentValueBinding="{Binding IndependentValue}" 
   AnimationSequence="Simultaneous" />
  </chartingToolkit:Chart.Series>
   <chartingToolkit:Chart.Axes>
    <chartingToolkit:LinearAxis Orientation="Y" ShowGridLines="False"/>
  </chartingToolkit:Chart.Axes>
</chartingToolkit:Chart

Give your advice to big bosses and make money

Views: 2347

Tags: , ,

Charting | Silverlight

Powered by BlogEngine.NET 1.5.1.7
Theme by Naveen Kohli

By Categories