Search code examples
uwptelerik

How to refresh a ScatterLineSeries?


Two questions about Telerik UI Controls for UWP

In a UWP app, I have a RadCartesianChart Control. With ScatterLine and ScatterArea series. With ItemsSource set to an ObservableCollection, Contained Objects are simple objects with X and Y properties, with INotifyPropertyChanged interface, so when X or Y properties are updated, they fire events of change values. Both X and Y value bindings are set to the corresponding properties in the ScatterLineSeries

Now, I understand the source being an ObservableCollection, the chart control updates automatically when I add or delete a point to the collection, but how I Refresh the chart when I modify the values of a point?, How i ask the chart control to re-query the data sources? Below is the Data Point class.

public class DataPoint : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private decimal x;
    private ComplexDecimal y;

    public decimal X { get => x; set { x = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("X")); } }
    public ComplexDecimal Y
    {
        get => y; set
        {
            y = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Y"));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PhaseDegDouble"));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("dBV"));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("dBm"));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("dBSPL"));
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Magnitude"));
        }
    }

    public double PhaseDegDouble { get => Y.PhaseDegDouble; }
    public double dBV { get => Y.TodBV; }
    public double dBSPL { get => Y.TodBSPL; }
    public double dBm { get => Y.TodBm; }
    public double Magnitude { get => Convert.ToDouble(Y.Magnitude); }

}

So I have a function object, with a field ObservableCollection Data I make a ScatterLineSeries.

var lineMag = new ScatterLineSeries()
{
ItemsSource = function.Data,
XValueBinding = new PropertyNameDataPointBinding("X"),
YValueBinding = new PropertyNameDataPointBinding("dBV"),
};

and add it to the Chart with
rcChart.Series.Add(lineMag);

If I do:

function.Data.Add(new DataPoint(){X=30,Y=new ComplexDecimal(1,1)});

point is added. But if I do:

function.Data[0].Y = new ComplexDecimal(1,1);

chart does not update. How do I update the chart when I modify an existing DataPoint? (ComplexDecimal is just a struct for complex number using decimal type for both real and imag parts)

And a minor question beside, with ScatterArea, area fills from 0 to value, but with my data I have negative values, and so the filled area looks from the curve to the top, i would like to get the fill, from the curve to negativeInfinity. Filled area is up!! Thank you!


Solution

  • Since you code sample still is incomplete. I just made a simple code sample to test. When the Binding works on the 'RadCartesianChart' control, I then updated the 'XValue' and 'YValue' from the collection. Then, there's no problem. The chart would be updated.

    Please see my code sample:

    <Grid>
        <telerikChart:RadCartesianChart x:Name="scatterLineSeries">
            <telerikChart:RadCartesianChart.VerticalAxis>
                <telerikChart:LinearAxis/>
            </telerikChart:RadCartesianChart.VerticalAxis>
            <telerikChart:RadCartesianChart.HorizontalAxis>
                <telerikChart:LinearAxis/>
            </telerikChart:RadCartesianChart.HorizontalAxis>
    
            <telerikChart:ScatterLineSeries ItemsSource="{Binding}">
                <telerikChart:ScatterLineSeries.XValueBinding>
                    <telerikChart:PropertyNameDataPointBinding PropertyName="XValue"/>
                </telerikChart:ScatterLineSeries.XValueBinding>
                <telerikChart:ScatterLineSeries.YValueBinding>
                    <telerikChart:PropertyNameDataPointBinding PropertyName="YValue"/>
                </telerikChart:ScatterLineSeries.YValueBinding>
            </telerikChart:ScatterLineSeries>
        </telerikChart:RadCartesianChart>
    
        <Button Content="update" Click="Button_Click"></Button>
    </Grid>
    
    public sealed partial class MainPage : Page
    {
        ObservableCollection<Data> sampleData;
        public MainPage()
        {
            this.InitializeComponent();
            sampleData = new ObservableCollection<Data>();
            sampleData.Add(new Data() { XValue = 2, YValue = 3 });
            sampleData.Add(new Data() { XValue = 3, YValue = 4 });
            sampleData.Add(new Data() { XValue = 4, YValue = 5 });
            sampleData.Add(new Data() { XValue = 5, YValue = 6 });
            sampleData.Add(new Data() { XValue = 6, YValue = 5 });
            sampleData.Add(new Data() { XValue = 7, YValue = 4 });
            sampleData.Add(new Data() { XValue = 8, YValue = 3 });
            sampleData.Add(new Data() { XValue = 9, YValue = 4 });
            sampleData.Add(new Data() { XValue = 10, YValue = 5 });
            sampleData.Add(new Data() { XValue = 11, YValue = 4 });
            sampleData.Add(new Data() { XValue = 12, YValue = 3 });
            sampleData.Add(new Data() { XValue = 13, YValue = 2 });
            sampleData.Add(new Data() { XValue = 14, YValue = 1 });
    
            this.scatterLineSeries.DataContext = sampleData;
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            sampleData[0].XValue = 10;
            sampleData[0].YValue = 5;
        }
    }
    
    public class Data : INotifyPropertyChanged
    {
        private double xValue;
        public double XValue
        {
            get => xValue;
            set
            {
                xValue = value;
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("XValue"));
            }
        }
    
        private double yValue;
        public double YValue
        {
            get => yValue;
            set
            {
                yValue = value;
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("YValue"));
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
    }