This is a migrated thread and some comments may be shown as answers.

Refreshing a chartview

1 Answer 500 Views
Chart
This is a migrated thread and some comments may be shown as answers.
Aaron
Top achievements
Rank 1
Aaron asked on 25 Jan 2016, 06:09 PM

I'm using the RadCartesianChart to display a dynamic number of series in a lineseries and am trying to get it to refresh automatically when the collection that drives the ChartSeriesProvider is changed. I am using the MVVM pattern.

This is the XAML defining my charts. 

<chart:RadCartesianChart Grid.Column="0" Grid.Row="0" x:Name="ColumnChart">
            <chart:RadCartesianChart.HorizontalAxis >
                <chartView:CategoricalAxis Title="Date" />
            </chart:RadCartesianChart.HorizontalAxis>
            <chart:RadCartesianChart.VerticalAxis>
                <chartView:LinearAxis Title="Value" />
            </chart:RadCartesianChart.VerticalAxis>
            <chart:RadCartesianChart.Behaviors>
                <chartView:ChartTooltipBehavior Placement="Top" VerticalOffset="20" />
                <chartView:ChartPanAndZoomBehavior ZoomMode="Both"/>
            </chart:RadCartesianChart.Behaviors>
            <chart:RadCartesianChart.SeriesProvider>
                <chartView:ChartSeriesProvider IsDynamicSeries="True" Source="{Binding FilteredSeries}">
                    <chartView:ChartSeriesProvider.SeriesDescriptors>
                        <chartView:CategoricalSeriesDescriptor ItemsSourcePath="Values" CategoryPath="Date" ValuePath="Value">
                            <chartView:CategoricalSeriesDescriptor.Style>
                                <Style TargetType="chartView:LineSeries">
                                    <Setter Property="StrokeThickness" Value="2"/>
                                    <Setter Property="PointTemplate" Value="{StaticResource PointTemplate}" />
                                </Style>
                            </chartView:CategoricalSeriesDescriptor.Style>
                        </chartView:CategoricalSeriesDescriptor>
                    </chartView:ChartSeriesProvider.SeriesDescriptors>
                </chartView:ChartSeriesProvider>
            </chart:RadCartesianChart.SeriesProvider>
        </chart:RadCartesianChart>

This is the View model driving the chart.

public class PostProcessingColumnChartViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<ChartSeries> _series;
        private ObservableCollection<long> _availableLineNumbers;
        private long _selectedLineNumber = -1;
 
        public PostProcessingColumnChartViewModel(PostProcessingEntry entry)
        {
            Name = entry.Name;
            AvailableLineNumbers.Add(-1);
            foreach (var postProcessingRecord in entry.Records)
            {
                if (!postProcessingRecord.Value.LineNumber.HasValue)
                    continue;
 
                var series = new ChartSeries()
                {
                    SerialNumber = postProcessingRecord.Value.SerialNumber,
                    LineNumber = postProcessingRecord.Value.LineNumber,
                    PointNumber = postProcessingRecord.Value.StationNumber
                };
                foreach (var value in postProcessingRecord.Value.Values)
                {
                    series.Values.Add(new ChartRecord() {Date = value.Key, Value = value.Value});
                }
                 
                Series.Add(series);
            }
            var lineNumbers = Series.Where(s => s.LineNumber.HasValue).Select(s => s.LineNumber.Value).Distinct().OrderBy(ln => ln).ToList();
            foreach (var lineNumber in lineNumbers)
            {
                AvailableLineNumbers.Add(lineNumber);
            }
        }
 
        public string Name { get; set; }
 
        public ObservableCollection<ChartSeries> Series => _series ?? (_series = new ObservableCollection<ChartSeries>());
 
        public ObservableCollection<long> AvailableLineNumbers => _availableLineNumbers ?? (_availableLineNumbers = new ObservableCollection<long>());
 
        public ObservableCollection<ChartSeries> FilteredSeries => new ObservableCollection<ChartSeries>(Series);
 
        public long SelectedLineNumber
        {
            get { return _selectedLineNumber; }
            set
            {
                if (_selectedLineNumber == value)
                    return;
 
                _selectedLineNumber = value;
                OnPropertyChanged();
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (propertyName != null && propertyName.Equals("SelectedLineNumber"))
            {
                FilteredSeries.Clear();
                if (SelectedLineNumber > -1)
                    foreach (var series in Series.Where(s => s.LineNumber == SelectedLineNumber))
                    {
                        FilteredSeries.Add(series);
                    }
                else
                    foreach (var series in Series)
                    {
                        FilteredSeries.Add(series);
                    }
            }
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

I have these charts in a tab control and if I try and filter one it doesn't change until I view a different graph and then come back to the one I filtered. I know this is because chart goes through the rebinding process and updates but I would like that to happen while the user is currently viewing that chart. Everything seems to beworking except for the chart not updating until a rebinding occurs.

1 Answer, 1 is accepted

Sort by
0
Aaron
Top achievements
Rank 1
answered on 25 Jan 2016, 06:44 PM

I seem to have found a fix for my problem. 

 The issue appears to be with my FilteredSeries collection. I had to make a backing field for it as creating it from the series wasn't allowing for the Collection changed event to fire. 

 Changing 

public ObservableCollection<ChartSeries> FilteredSeries => new ObservableCollection<ChartSeries>(Series);

 to

private ObservableCollection<ChartSeries> _filterSeries;
public ObservableCollection<ChartSeries> FilterSeries => _filterSeries ?? (_filterSeries = new ObservableCollection<ChartSeries>());

resolved the issue.

Tags
Chart
Asked by
Aaron
Top achievements
Rank 1
Answers by
Aaron
Top achievements
Rank 1
Share this question
or