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();
}
}
}