Position of TrackBall info items in popup?

2 posts, 0 answers
  1. Jesper
    Jesper avatar
    18 posts
    Member since:
    Jun 2012

    Posted 12 Jul 2012 Link to this post

    In the chart I'm developing the user needs to be able to exclude or include series at runtime. 

    If I have understood the information correctly so far it is not possible to XAML-declare series on this kind of dynamic sources but that it is something you're considering for a future update. I didn't want to do it all using code behind becuase that would mess up my ability to declare templates for each series and its trackball.

    So, instead I build a small ChartBehavior that acts as the "glue" between my dynamic data series and the chart. It works as expected except for one detail: A series that gets omitted and then included again always ends up at the bottom of the trackball info popup. I assumed that the order of the items in the trackball popup was based on the physical order of the Chart.Series collection so the the behavior saves the initial order to be able to re-insert an omitted series at its original position but this does not work.

    How can I affect the order of the items in the trackball info popup?

    internal sealed class DynamicCategoricalSeriesBehavior : ChartBehavior
    {
        private class SeriesInfo
        {
            public string SeriesKey { get; private set; }
            public int Index { get; set; }
     
            public SeriesInfo(string seriesKey, int seriesIndex)
            {
                Index = seriesIndex;
                SeriesKey = seriesKey;
            }
        }
        private Dictionary<CategoricalSeries, SeriesInfo> _categoricalSeries;
     
        protected override void OnAttached()
        {
            base.OnAttached();
            Chart.DataContextChanged += chartDataContextChanged;
            listenToDataContextPropertyChanged(Chart.DataContext as INotifyPropertyChanged);
        }
     
        protected override void OnChartTemplateChanged(Canvas oldAdornerContainer, Canvas adornerContainer)
        {
            base.OnChartTemplateChanged(oldAdornerContainer, adornerContainer);
            saveCategoricalSeriesValuePropertyNames();
            transformMetricsForSeries(Chart as RadCartesianChart);
        }
     
        private void saveCategoricalSeriesValuePropertyNames()
        {
            var cartesianChart = Chart as RadCartesianChart;
            if (cartesianChart == null)
                return;
     
            _categoricalSeries = new Dictionary<CategoricalSeries, SeriesInfo>();
            var seriesIndex = 0;
            foreach (var series in cartesianChart.Series)
            {
                var catSeries = series as CategoricalSeries;
                if (catSeries == null)
                    continue;
     
                var propertyNameValueBinding = catSeries.ValueBinding as PropertyNameDataPointBinding;
                if (propertyNameValueBinding == null)
                    continue;
     
                _categoricalSeries[catSeries] = new SeriesInfo(propertyNameValueBinding.PropertyName, seriesIndex++);
            }
        }
     
        private void chartDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            listenToDataContextPropertyChanged(Chart.DataContext as INotifyPropertyChanged);
        }
     
        private void listenToDataContextPropertyChanged(INotifyPropertyChanged vm)
        {
            if (vm == null)
                return;
     
            vm.PropertyChanged += (o, args) =>
            {
                if (args.PropertyName == "DynamicDataSeries")
                    transformMetricsForSeries(Chart as RadCartesianChart);
            };
        }
     
        private void transformMetricsForSeries(RadCartesianChart chart)
        {
            if (chart == null)
                return;
     
            var dynamicVM = Chart.DataContext as IDynamicMetricsValueSeriesProvider<double>;
            if (dynamicVM == null)
                return;
     
            var supportedSeries = dynamicVM.DynamicDataSeries.Select(series => series.SeriesKey).ToList();
     
            foreach (var kvp in _categoricalSeries)
            {
                var series = kvp.Key;
                var seriesKey = kvp.Value.SeriesKey;
                if (!supportedSeries.Contains(seriesKey))
                {
                    removeSeries(chart, series, seriesKey);
                    continue;
                }
                insertSeries(chart, series, seriesKey, dynamicVM);
            }
        }
     
        private void insertSeries(RadCartesianChart chart, CategoricalSeries series, string key, IDynamicMetricsValueSeriesProvider<double> seriesProvider)
        {
            if (series.Visibility != Visibility.Visible)
            {
                series.Visibility = Visibility.Visible;
                var index = _categoricalSeries[series].Index;
                chart.Series.Insert(index, series);
            }
            var dataPoints = seriesProvider.MetricsData.Where(i => i.MetricsId == key).ToList();
            series.ValueBinding = new PropertyNameDataPointBinding("Value");
            series.ItemsSource = dataPoints;
            var stroked = series as CategoricalStrokedSeries;
            if (stroked != null)
                stroked.Stroke = seriesProvider.GetMetricsDataColorBrush(key);
        }
     
        private void removeSeries(RadCartesianChart chart, CategoricalSeries series, string key)
        {
            chart.Series.Remove(series);
            series.Visibility = Visibility.Collapsed;
        }
    }


  2. Giuseppe
    Admin
    Giuseppe avatar
    2363 posts

    Posted 17 Jul 2012 Link to this post

    Hello Jesper,

    Currently there is no public API that can control the order of series / indicators in the TrackBallInfo template -- it is indeed based on the chart series ordering. However, due to the specifics of the current internal implementation of the control (every series visual is associated with respective "data" model class and the model actually dictates the order), the "Insert" operation is not supported properly and is handled as "Add" -- that is why you are observing the unexpected behavior in your scenario. We have logged this problem in our public issue tracking system here and will forward it to our developers for further review. As a workaround we would suggest you to clear the whole series collection every time you need to change the series count dynamically, and then re-add the necessary series (instead of using Insert calls).

    Sorry for the inconvenience.


    Regards,
    Giuseppe
    the Telerik team

    Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.

  3. UI for WPF is Visual Studio 2017 Ready
Back to Top