Refreshing a chartview

2 posts, 0 answers
  1. Aaron
    Aaron avatar
    2 posts
    Member since:
    Apr 2013

    Posted 25 Jan Link to this post

    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.

  2. Aaron
    Aaron avatar
    2 posts
    Member since:
    Apr 2013

    Posted 25 Jan Link to this post

    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.

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