RadCartesianChart not showing annotations in datatemplate

3 posts, 1 answers
  1. Hans
    Hans avatar
    2 posts
    Member since:
    Nov 2013

    Posted 04 Mar Link to this post

    Hi Telerik,

     

    I'm having this strange phenomenon where my RadCartesianChart shows my annotations when I create the control directly on the grid of the usercontrol, but not when I try to access it in a datatemplate. The annotations are added to the chart in code behind. In both cases, the code is executed, but I don't see them when using the datatemplate. The lineseries themselves are shown in both cases.

    This is the XAML for the chart in the datatemplate:

    <DataTemplate DataType="{x:Type entities:ChartMeasurement}">
                <Grid>
                    <telerik:RadCartesianChart Grid.Row="0" HorizontalAlignment="Stretch" Margin="240,15,0,39" Name="radCartesianChart">
                        <telerik:RadCartesianChart.Resources>
                            <DataTemplate x:Key="PointTemplate">
                                <Ellipse Height="8" Width="8" Stroke="White" StrokeThickness="1" Fill="#1B9DDE" />
                            </DataTemplate>
                            <Style x:Key="BorderStyle" TargetType="Border">
                                <Setter Property="Background" Value="#1B9DDE" />
                            </Style>
                        </telerik:RadCartesianChart.Resources>
                        <telerik:RadCartesianChart.HorizontalAxis>
                            <telerik:DateTimeContinuousAxis MajorStep="{Binding MyViewModel.MajorStep}"
                                                        MajorStepUnit="{Binding MyViewModel.MajorStepUnit}"
                                                        PlotMode="OnTicksPadded"
                                                        LabelTemplate="{StaticResource HorizontalAxisLabelTemplate}"
                                                        LabelRotationAngle="-90"
                                                        LabelFitMode="Rotate"
                                                        LineThickness="2"
                                                        LineStroke="Gray"/>
                        </telerik:RadCartesianChart.HorizontalAxis>
                        <telerik:RadCartesianChart.VerticalAxis>
                            <telerik:LinearAxis Visibility="Hidden"/>
                        </telerik:RadCartesianChart.VerticalAxis>
                        <telerik:RadCartesianChart.SeriesProvider>
                            <telerik:ChartSeriesProvider x:Name="myChartSeriesProvider" Source="{Binding MyViewModel.ChartData.MeasurementList}">
                                <telerik:ChartSeriesProvider.SeriesDescriptors>
                                    <telerik:CategoricalSeriesDescriptor ItemsSourcePath="RawDataList" ValuePath="Value" CategoryPath="Time_Local">
                                        <telerik:CategoricalSeriesDescriptor.Style>
                                            <Style TargetType="telerik:LineSeries">
                                                <Setter Property="StrokeThickness" Value="2"/>
                                                <Setter Property="Stroke" Value="{Binding GraphColorBrush}"/>
                                                <Setter Property="VerticalAxis" Value="{Binding VerticalAxis}"/>
                                                <Setter Property="LegendSettings" Value="{Binding Measurement.Name, Converter={StaticResource LegendSettings}}"/>
                                            </Style>
                                        </telerik:CategoricalSeriesDescriptor.Style>
                                    </telerik:CategoricalSeriesDescriptor>
                                </telerik:ChartSeriesProvider.SeriesDescriptors>
                            </telerik:ChartSeriesProvider>
                        </telerik:RadCartesianChart.SeriesProvider>
                        <telerik:RadCartesianChart.Grid>
                            <telerik:CartesianChartGrid MajorXLinesRenderMode="All" MajorLinesVisibility="XY"/>
                        </telerik:RadCartesianChart.Grid>
                    </telerik:RadCartesianChart>
                    <telerik:RadLegend Items="{Binding LegendItems, ElementName=radCartesianChart}"
                                                   FontFamily="Segoe UI"
                                                   Grid.Row="0"
                                                   Margin="2 52 30 20"/>
                </Grid>
    </DataTemplate>

    As you can see, it is a quite complex graph with a dynamic number of series and 2 vertical axises, where I wan't to combine a number of series on the left vertical axis, and a number of series on the right vertical axis

    This is the ChartMeasurement class used in the datatemplate:

    public class ChartMeasurement : Measurement
        {
            private ReportingViewModel _reportingViewModel;

            public ChartMeasurement(ReportingViewModel reportingViewModel)
            {
                _reportingViewModel = reportingViewModel;
                MeasurementSignal = new Signal { Name = "Graph" };
            }

            public ReportingViewModel MyViewModel
            {
                get { return _reportingViewModel; }
            }
        }

    In code behind, I to the following:

    private void RadComboBoxMeasurementPoints_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                var reportingView = DataContext as ReportingViewModel;
                var measurementPoint = e.AddedItems[0] as MeasurementPoint;

                var dataTemplateKey = new DataTemplateKey(typeof(ChartMeasurement));
                var dataTemplate = FindResource(dataTemplateKey) as DataTemplate;
                if (dataTemplate == null)
                {
                    return;
                }
                var radCartesianChart = ((Grid)dataTemplate.LoadContent()).Children[0] as RadCartesianChart;
                if (reportingView != null &&
                    measurementPoint != null &&
                    radCartesianChart != null)
                {
                    radCartesianChart.Annotations.Clear();

                    var axisLeft = new LinearAxis
                    {
                        Title = "",
                        Minimum = 0,
                        Maximum = measurementPoint.ScaleLeft,
                        HorizontalLocation = AxisHorizontalLocation.Left,
                        TickThickness = 1,
                        MajorTickLength = 2,
                        LineThickness = 2,
                        MajorStep = measurementPoint.ScaleLeft / 10
                    };

                    var axisRight = new LinearAxis
                    {
                        Title = "",
                        Minimum = 0,
                        Maximum = measurementPoint.ScaleRight,
                        HorizontalLocation = AxisHorizontalLocation.Right,
                        TickThickness = 1,
                        MajorTickLength = 2,
                        LineThickness = 2,
                        MajorStep = measurementPoint.ScaleRight / 10
                    };

                    if (reportingView.ReportData == null)
                    {
                        return;
                    }
                    var stringLeft = new List<String>();
                    var stringRight = new List<String>();
                    foreach (var measurement in reportingView.ReportData.Measurements.Where(m => m.Measurement.MeasurementPoint.Equals(e.AddedItems[0])))
                    {
                        if (!measurement.Measurement.HasAxisLeft)
                        {
                            measurement.VerticalAxis = axisRight;
                            stringRight.Add(measurement.Measurement.Name);
                            if (measurement.Measurement.HasBoundaryValue)
                            {
                                radCartesianChart.Annotations.Add(new CartesianGridLineAnnotation
                                {
                                    Value = measurement.Measurement.BoundaryValue,
                                    Stroke = measurement.GraphColorBrush,
                                    Axis = axisRight,
                                    Label = measurement.Measurement.Name
                                });
                            }
                        }
                        else
                        {
                            measurement.VerticalAxis = axisLeft;
                            stringLeft.Add(measurement.Measurement.Name);
                            if (measurement.Measurement.HasBoundaryValue)
                            {
                                radCartesianChart.Annotations.Add(new CartesianGridLineAnnotation
                                {
                                    Value = measurement.Measurement.BoundaryValue,
                                    Stroke = measurement.GraphColorBrush,
                                    Axis = axisLeft,
                                    Label = measurement.Measurement.Name
                                });
                            }
                        }
                    }
                    axisRight.Title = String.Join(", ", stringRight);
                    axisLeft.Title = String.Join(", ", stringLeft);
                }
            }

    This code is executed each time another measurementpoint is selected, but I never see the annotations. The lineseries are shown as expected.

    When I omit the datatemplate, and show the chart directly in the grid, it works just fine.

    This is the XAML:

    <telerik:RadCartesianChart Grid.Row="1" HorizontalAlignment="Stretch" Margin="240,15,0,39" Name="radCartesianChart">
                    <telerik:RadCartesianChart.Resources>
                        <DataTemplate x:Key="PointTemplate">
                            <Ellipse Height="8" Width="8" Stroke="White" StrokeThickness="1" Fill="#1B9DDE" />
                        </DataTemplate>
                        <Style x:Key="BorderStyle" TargetType="Border">
                            <Setter Property="Background" Value="#1B9DDE" />
                        </Style>
                    </telerik:RadCartesianChart.Resources>
                    <telerik:RadCartesianChart.HorizontalAxis>
                        <telerik:DateTimeContinuousAxis MajorStep="{Binding MajorStep}"
                                                        MajorStepUnit="{Binding MajorStepUnit}"
                                                        PlotMode="OnTicksPadded"
                                                        LabelTemplate="{StaticResource HorizontalAxisLabelTemplate}"
                                                        LabelRotationAngle="-90"
                                                        LabelFitMode="Rotate"
                                                        LineThickness="2"
                                                        LineStroke="Gray"/>
                    </telerik:RadCartesianChart.HorizontalAxis>
                    <telerik:RadCartesianChart.VerticalAxis>
                        <telerik:LinearAxis Visibility="Hidden"/>
                    </telerik:RadCartesianChart.VerticalAxis>
                    <telerik:RadCartesianChart.SeriesProvider>
                        <telerik:ChartSeriesProvider Source="{Binding ChartData.MeasurementList, Mode=TwoWay}">
                            <telerik:ChartSeriesProvider.SeriesDescriptors>
                                <telerik:CategoricalSeriesDescriptor ItemsSourcePath="RawDataList" ValuePath="Value" CategoryPath="Time_Local">
                                    <telerik:CategoricalSeriesDescriptor.Style>
                                        <Style TargetType="telerik:LineSeries">
                                            <Setter Property="StrokeThickness" Value="2"/>
                                            <Setter Property="Stroke" Value="{Binding GraphColorBrush}"/>
                                            <Setter Property="VerticalAxis" Value="{Binding VerticalAxis}"/>
                                            <Setter Property="LegendSettings" Value="{Binding Measurement.Name, Converter={StaticResource LegendSettings}}"/>
                                        </Style>
                                    </telerik:CategoricalSeriesDescriptor.Style>
                                </telerik:CategoricalSeriesDescriptor>
                            </telerik:ChartSeriesProvider.SeriesDescriptors>
                        </telerik:ChartSeriesProvider>
                    </telerik:RadCartesianChart.SeriesProvider>
                    <telerik:RadCartesianChart.Grid>
                        <telerik:CartesianChartGrid MajorXLinesRenderMode="All" MajorLinesVisibility="XY"/>
                    </telerik:RadCartesianChart.Grid>
                </telerik:RadCartesianChart>
                <telerik:RadLegend Items="{Binding LegendItems, ElementName=radCartesianChart}"
                                   Name="radLegend"
                                   FontFamily="Segoe UI"
                                   Grid.Row="1"
                                   Margin="2 52 30 20"/>

     

    And the code behind:

    private void RadComboBoxMeasurementPoints_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                var reportingView = DataContext as ReportingViewModel;
                var measurementPoint = e.AddedItems[0] as MeasurementPoint;

                if (reportingView != null &&
                    measurementPoint != null &&
                    radCartesianChart != null)
                {
                    radCartesianChart.Annotations.Clear();

                    var axisLeft = new LinearAxis
                    {
                        Title = "",
                        Minimum = 0,
                        Maximum = measurementPoint.ScaleLeft,
                        HorizontalLocation = AxisHorizontalLocation.Left,
                        TickThickness = 1,
                        MajorTickLength = 2,
                        LineThickness = 2,
                        MajorStep = measurementPoint.ScaleLeft / 10
                    };

                    var axisRight = new LinearAxis
                    {
                        Title = "",
                        Minimum = 0,
                        Maximum = measurementPoint.ScaleRight,
                        HorizontalLocation = AxisHorizontalLocation.Right,
                        TickThickness = 1,
                        MajorTickLength = 2,
                        LineThickness = 2,
                        MajorStep = measurementPoint.ScaleRight / 10
                    };

                    if (reportingView.ReportData == null)
                    {
                        return;
                    }
                    var stringLeft = new List<String>();
                    var stringRight = new List<String>();
                    foreach (var measurement in reportingView.ReportData.Measurements.Where(m => m.Measurement.MeasurementPoint.Equals(e.AddedItems[0])))
                    {
                        if (!measurement.Measurement.HasAxisLeft)
                        {
                            measurement.VerticalAxis = axisRight;
                            stringRight.Add(measurement.Measurement.Name);
                            if (measurement.Measurement.HasBoundaryValue)
                            {
                                radCartesianChart.Annotations.Add(new CartesianGridLineAnnotation
                                {
                                    Value = measurement.Measurement.BoundaryValue,
                                    Stroke = measurement.GraphColorBrush,
                                    Axis = axisRight,
                                    Label = measurement.Measurement.Name
                                });
                            }
                        }
                        else
                        {
                            measurement.VerticalAxis = axisLeft;
                            stringLeft.Add(measurement.Measurement.Name);
                            if (measurement.Measurement.HasBoundaryValue)
                            {
                                radCartesianChart.Annotations.Add(new CartesianGridLineAnnotation
                                {
                                    Value = measurement.Measurement.BoundaryValue,
                                    Stroke = measurement.GraphColorBrush,
                                    Axis = axisLeft,
                                    Label = measurement.Measurement.Name
                                });
                            }
                        }
                    }
                    axisRight.Title = String.Join(", ", stringRight);
                    axisLeft.Title = String.Join(", ", stringLeft);
                    dataTemplate.LoadContent();
                }
            }

     

    As you can see, both code snippets are very alike.

    What am I missing here or doing wrong?

    The reason for using a datatemplate is that I want the chart to show up in a tab page of a dynamic tab control (dynamic number of tab pages).

     

    Thanks in advance.

     

    Hans.

  2. Answer
    Martin
    Admin
    Martin avatar
    1101 posts

    Posted 09 Mar Link to this post

    Hello Hans,

    I tested the described scenario and I can confirm that the annotations added at runtime are not displayed in the chart, when it is in a DataTemplate. This is observed because the LoadContent() method of the DataTemplate object is used to load the chart from the template. Note that this method won't return the element loaded in the visual tree of the application, but a new instance of it. So, basically, you add the annotations in a new chart which is never presented in the visual tree.

    In order to achieve your requirement you can try out the new AnnotationsProvider feature of RadCartesianChart which allows you to bind the annotations collection of the chart to a collection of models that describe the annotations. This will allow you to work with the view model in the SelectionChanged event handler, instead of the chart control directly. You can find a runnable example that demonstrates how the provider is used in the AnnotationsProvider SDK example.

    Regards,
    Martin
    Telerik
    Do you need help with upgrading your AJAX, WPF or WinForms project? Check the Telerik API Analyzer and share your thoughts.
     
  3. UI for WPF is Visual Studio 2017 Ready
  4. Hans
    Hans avatar
    2 posts
    Member since:
    Nov 2013

    Posted 10 Mar in reply to Martin Link to this post

    Hi Martin,

     

    many thanks for your answer. I was already guessing something was happening like what you describe.

    I was indeed waiting for some kind of ItemsSource mechanism for annotations so I can bind them to my viewmodel.

    I'll give it a try a soon as possible.

     

    Kind regards,

     

    Hans.

Back to Top