RadChartView ScatterSeries - Make data fill the plot area

1 Answer 161 Views
ChartView
Dimitrios
Top achievements
Rank 1
Dimitrios asked on 20 Jan 2023, 04:57 PM

I have a ScatterSeries  within a RadChartView which is bound to a BindingList of x-y plot points.

When the BindingList updates, the points on the chart are re-plotted , but are being plotted in the middle of the chart, with a large amount of whitespace between the extreme values and the bounds of the chart. The Maximum and Minimum axes values are seemingly decided automatically and at random (if there is some logic to amount of the whitespace being applied, I cannot discern it).

I would like the leftmost plot ploint to be flush with the leftmost axis, the right most plot point to beflush with the right axis, etc. (i.e. I want the axes to be "tight" around the data).

I can do this manually for a known data set with the following code:

LinearAxis horizontalAxis = radChartView1.Axes.Get<LinearAxis>(0);
// or verticalAxis = series.VerticalAxis as LinearAxis;
horizontalAxis.Minimum = 1;
horizontalAxis.Maximum = 7;

Is there a way I can apply this to ensure that the axes are flush with the outermost data points every time the chart is updated due to the binding? Is there a way  to do this without manually setting values for the axes Maximum and Minimum?

I tried applying the following setting to the axis but it does not seem to produce the desired effect; there is still whitespace between the plotted data and the left and right borders of the plot.

horizontal.RangeExtendDirection = NumericalAxisRangeExtendDirection.None;

1 Answer, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 23 Jan 2023, 01:49 PM
Hello, Dimitrios,

Usually, the minimum/maximum range of the horizontal axis depends on the actual plotted data. Hence, whenever you update the bound objects, the chart is expected to be updated as well and the horizontal axis should update its range accordingly. 

The LinearAxis has a MajorStep property determining the step at which each of the ticks will be plotted. By default the axis itself will calculate the major step, depending on the plotted data points. The axis also has a Minimum and Maximum properties defining and min and max values it can display. The RangeExtendDirection value specifies how the auto-range of this axis is extended so that each data point is visualized in the best way. Possible values are None, Positive, Negative, Both. None sets the range minimum to the minimum data point value and the range maximum to the maximum data point value. Positive extends the range maximum with one major step if necessary. Negative extends the range minimum with one major step if necessary. Both extend the range in both negative and positive direction.

I have prepared a sample code snippet for your reference which result is illustrated in the below gif file:
    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        BindingList<MyCustomObject> myList;
        Random rand = new Random();
          ScatterSeries scatterSeries = new ScatterSeries(); 
        public RadForm1()
        {
            InitializeComponent();

            scatterSeries.PointSize = new SizeF(8, 8); 
            this.radChartView1.Series.Add(scatterSeries);

            myList = new BindingList<MyCustomObject>();
            myList = new BindingList<MyCustomObject>();
            myList.Add(new MyCustomObject(1, 3));
            myList.Add(new MyCustomObject(8, 32));
            myList.Add(new MyCustomObject(3, 12));
            myList.Add(new MyCustomObject(6, 16));
            myList.Add(new MyCustomObject(2, 24));

            scatterSeries.BackColor = Color.Red;
            scatterSeries.ShowLabels = true;
            scatterSeries.DataSource = myList;
            scatterSeries.XValueMember  = "MyX";
            scatterSeries.YValueMember  = "MyY";
             
            ((LinearAxis)scatterSeries.HorizontalAxis).RangeExtendDirection = Telerik.Charting.NumericalAxisRangeExtendDirection.None;
        }

        

        private void radButton1_Click(object sender, EventArgs e)
        {
            foreach (MyCustomObject obj in myList)
            {
                obj.MyX = rand.Next(5, 30);
                Thread.Sleep(100);
                obj.MyY = rand.Next(5, 30);
            }
        }
    }

    public class MyCustomObject : INotifyPropertyChanged
        {
            private int _myX;
            private int _myY;

            public MyCustomObject(int x, int y)
            {
                _myX = x;
                _myY = y;
            }

            public int MyX
            {
                get
                {
                    return _myX;
                }
                set
                {
                    _myX = value;
                    OnPropertyChanged("MyX");
                }
            }

            public int MyY
            {
                get
                {
                    return _myY;
                }
                set
                {
                    _myY = value;
                    OnPropertyChanged("MyY");
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;

            protected virtual void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }

I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Principal
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Dimitrios
Top achievements
Rank 1
commented on 23 Jan 2023, 02:56 PM | edited

Hi Dess,

Thanks for your response. The example you have given follows the same process as my code.

After some digging, it seems that while this seems to work for integer values, if the plot points are non-integer, whitespace appears around the plot points.

For example, if you replace your example plot points,

myList.Add(new MyCustomObject(1, 3));
myList.Add(new MyCustomObject(8, 32));
myList.Add(new MyCustomObject(3, 12));
myList.Add(new MyCustomObject(6, 16));
myList.Add(new MyCustomObject(2, 24));

with the following:

myList.Add(new MyCustomObject(1.53, 3));
myList.Add(new MyCustomObject(8.15, 32));
myList.Add(new MyCustomObject(3.937, 12));
myList.Add(new MyCustomObject(6.173, 16));
myList.Add(new MyCustomObject(2.23, 24));

I see white space around the plot; see the attached image.

Is it possible to achieve the same effect with non-integer values?

Dess | Tech Support Engineer, Principal
Telerik team
commented on 24 Jan 2023, 01:37 PM

Hi, Dimitrios,

I have update my sample code snippet to add double X values and the below gif file illustrates the result on my end how the linear axis gets updated accordingly: 

    public partial class RadForm1 : Telerik.WinControls.UI.RadForm
    {
        BindingList<MyCustomObject> myList;
        Random rand = new Random();
        ScatterSeries scatterSeries = new ScatterSeries();
        public RadForm1()
        {
            InitializeComponent();

            scatterSeries.PointSize = new SizeF(8, 8);
            this.radChartView1.Series.Add(scatterSeries);

            myList = new BindingList<MyCustomObject>();
            myList = new BindingList<MyCustomObject>();
            //myList.Add(new MyCustomObject(1, 3));
            //myList.Add(new MyCustomObject(8, 32));
            //myList.Add(new MyCustomObject(3, 12));
            //myList.Add(new MyCustomObject(6, 16));
            //myList.Add(new MyCustomObject(2, 24));

            myList.Add(new MyCustomObject(1.53, 3));
            myList.Add(new MyCustomObject(8.15, 32));
            myList.Add(new MyCustomObject(3.937, 12));
            myList.Add(new MyCustomObject(6.173, 16));
            myList.Add(new MyCustomObject(2.23, 24));

            scatterSeries.BackColor = Color.Red;
            scatterSeries.ShowLabels = true;
            scatterSeries.DataSource = myList;
            scatterSeries.XValueMember = "MyX";
            scatterSeries.YValueMember = "MyY";
            this.radChartView1.ShowTrackBall = true;

            ((LinearAxis)scatterSeries.HorizontalAxis).RangeExtendDirection = Telerik.Charting.NumericalAxisRangeExtendDirection.None;
        }



        private void radButton1_Click(object sender, EventArgs e)
        {
            foreach (MyCustomObject obj in myList)
            {
                obj.MyX = (double)rand.Next(200, 3000) / 100;
                Thread.Sleep(100);
                obj.MyY = rand.Next(5, 30);
            }
        }
    }

    public class MyCustomObject : INotifyPropertyChanged
    {
        private double _myX;
        private int _myY;

        public MyCustomObject(double x, int y)
        {
            _myX = x;
            _myY = y;
        }

        public double MyX
        {
            get
            {
                return _myX;
            }
            set
            {
                _myX = value;
                OnPropertyChanged("MyX");
            }
        }

        public int MyY
        {
            get
            {
                return _myY;
            }
            set
            {
                _myY = value;
                OnPropertyChanged("MyY");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

 

If the default recalculation of the values on the horizontal axis doesn't fit your requirement, you can specify the desired MajorStep, Minimum, Maximum of the LinearAxis considering the values you have in the data records.

Tags
ChartView
Asked by
Dimitrios
Top achievements
Rank 1
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or