I've come across a strange problem when trying to use RelativeSource binding in the DataTemplate used for styling the LabelTemplate of an axis. When RelativeSource binding is used, the labels are drawn over the left side of the chart instead of to the left.
Below is the code for a simple example exhibiting the problem. (It's obviously a convoluted example since the numbers are all being set to the same value. In my real application I experienced the problem using MultiBinding to pass in some settings as well as the value, but this simpler example shows the same symptoms with single Binding).
If I bind to the Property using ElementName, it displays correctly. However, if I reference the exact same property using RelativeSource, the value is picked up successfully, but the labels are displayed incorrectly. See attached screen shot.
I have a work-around by using the ElementName, but ideally I'd like to use the RelativeSource instead to reference the owning ChartView such that the formatter can be put in a dictionary and used across several charts without having to assign them all the same name.
Thanks,
Louis
The sample app:
The code-behind:
Below is the code for a simple example exhibiting the problem. (It's obviously a convoluted example since the numbers are all being set to the same value. In my real application I experienced the problem using MultiBinding to pass in some settings as well as the value, but this simpler example shows the same symptoms with single Binding).
If I bind to the Property using ElementName, it displays correctly. However, if I reference the exact same property using RelativeSource, the value is picked up successfully, but the labels are displayed incorrectly. See attached screen shot.
I have a work-around by using the ElementName, but ideally I'd like to use the RelativeSource instead to reference the owning ChartView such that the formatter can be put in a dictionary and used across several charts without having to assign them all the same name.
Thanks,
Louis
The sample app:
<Window x:Class="LabelTemplate_MultiBinding.MainWindow" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" xmlns:local="clr-namespace:LabelTemplate_MultiBinding" Title="MainWindow" Height="768" Width="1024"> <Grid> <telerik:RadCartesianChart x:Name="PropertyChart"> <telerik:RadCartesianChart.Resources> <local:ChartNumberFormatter x:Key="NumberFormatter"/> <DataTemplate x:Key="FormattedNumericAxisTemplate"> <!-- This uses the converter sending the desired value, and it works fine --> <!--<TextBlock Text="{Binding ., Converter={StaticResource NumberFormatter}}" />--> <!-- This uses the converter sending some value via binding using ElementName, and it works fine --> <!--<TextBlock Text="{Binding Path=DataContext.JustANumber, Converter={StaticResource NumberFormatter}, ElementName=PropertyChart}" />--> <!-- This uses the converter sending the same value as above via binding, but using RelativeSource instead, and it displays incorrectly! --> <TextBlock Text="{Binding Path=DataContext.JustANumber, Converter={StaticResource NumberFormatter}, RelativeSource={RelativeSource AncestorType={x:Type telerik:RadCartesianChart}}}" /> </DataTemplate> </telerik:RadCartesianChart.Resources> <telerik:RadCartesianChart.HorizontalAxis> <telerik:DateTimeCategoricalAxis/> </telerik:RadCartesianChart.HorizontalAxis> <telerik:RadCartesianChart.VerticalAxis> <telerik:LinearAxis LabelTemplate="{StaticResource FormattedNumericAxisTemplate}" /> </telerik:RadCartesianChart.VerticalAxis> <telerik:RadCartesianChart.Series> <telerik:LineSeries CategoryBinding="Date" ValueBinding="Value" ItemsSource="{Binding Path=Series1}"> </telerik:LineSeries> </telerik:RadCartesianChart.Series> </telerik:RadCartesianChart> </Grid></Window>The code-behind:
using System;using System.Collections.Generic;using System.Windows;using System.Windows.Data;namespace LabelTemplate_MultiBinding{ public class MyPoint { public DateTime Date { get; set; } public Double Value { get; set; } } public partial class MainWindow : Window { public List<MyPoint> Series1 { get; private set; } public string DisplaySuffix { get; private set; } public double JustANumber { get; private set; } public MainWindow() { Series1 = new List<MyPoint>(); DisplaySuffix = "M"; JustANumber = 50000; for (int i = 0; i < 5; i++) { DateTime date = DateTime.Today.AddDays(i); Series1.Add(new MyPoint() { Date = date, Value = i * 1000 }); } InitializeComponent(); DataContext = this; } } public class ChartNumberFormatter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { double number = System.Convert.ToDouble(value); return number.ToString("N0"); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }}