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

Are there any samples for drawing points on LineSeries?

5 Answers 72 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Johnny
Top achievements
Rank 1
Veteran
Johnny asked on 19 Jan 2021, 04:59 AM

As title.

I need to change specific point style on LineSeries.

5 Answers, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 19 Jan 2021, 08:03 AM
Hello, Johnny, 

If you need to customize certain points, you can iterate the LineSeries.Children collection and apply the desired style for the respective point element. You can find below a sample approach: 
//populate the chart with data
            
           foreach (CartesianLinePointElement pointElement in lineSeria.Children)
            {
                CategoricalDataPoint dataPoint = pointElement.DataPoint as CategoricalDataPoint;
                if (dataPoint.Value > 10) 
                {
                    pointElement.BackColor = Color.Aqua;
                    pointElement.BorderColor = Color.Red;
                    pointElement.BorderWidth = 1;
                    pointElement.PointSize = new SizeF(15, 15);
                }
            }

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

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Johnny
Top achievements
Rank 1
Veteran
answered on 19 Jan 2021, 08:23 AM

Thank for your reply.

Actually, I mean custom render for drawing points on LineSeries.

0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 19 Jan 2021, 10:35 AM
Hello, Johnny, 

RadChartView provides a convenient way to control the rendering of series and data points by using a custom renderer. A sample approach is available here: https://docs.telerik.com/devtools/winforms/controls/chartview/customization/custom-rendering 

I would recommend you to download the Telerik source code from your account and have a look at the default implementation that LineSeriesDrawPart offers. In its DrawPoints method you can get familiar with the exact rendering of the points and you can add any customizations to the available implementation.  

Should you have further questions please let me know.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Johnny
Top achievements
Rank 1
Veteran
answered on 21 Jan 2021, 03:57 PM

I found my preferred way.

public class CustomLineSeriesDrawPart : LineSeriesDrawPart
{
    private static readonly FieldInfo IsEmptyFieldOfDataPoint = typeof(DataPoint).GetField(
        "isEmpty",
        BindingFlags.Instance | BindingFlags.NonPublic);
 
    public CustomLineSeriesDrawPart(LineSeriesBase series, IChartRenderer renderer)
        : base(series, renderer)
    {
    }
 
    protected override void DrawPoints()
    {
        var points = this.GetPointsPositionsArray();
 
        if (points == null) return;
 
        var radGraphics = new RadGdiGraphics(this.Renderer.Surface as Graphics);
 
        var pointElements = new List<DataPointElement>();
        var comparer = new DataPointElementLayoutSlotComparer();
 
        if (this.Renderer is CartesianRenderer cartesianRenderer)
        {
            comparer.Vertical = cartesianRenderer.Area.Orientation == Orientation.Vertical;
        }
 
        comparer.Collection = this.Element.DataPoints;
 
        for (var i = 0; i < this.Element.Children.Count; i++)
        {
            var pointElement = this.Element.Children[i] as DataPointElement;
            var index = pointElements.BinarySearch(pointElement, comparer);
 
            pointElements.Insert(~index, pointElement);
        }
 
        for (var i = 0; i < pointElements.Count; i++)
        {
            var childElement = pointElements[i];
 
            if (childElement == null) continue;
            if (!childElement.IsVisible) continue;
            if ((bool)IsEmptyFieldOfDataPoint.GetValue(pointElements[i].DataPoint)) continue;
            if (childElement.PointSize.Width < 1f) continue;
            if (childElement.PointSize.Height < 1f) continue;
 
            ChangePointStyle(childElement, out var pointSize);
 
            var pointLocation = points[i];
            var pointRect = new RectangleF(pointLocation, pointSize);
 
            pointRect.Offset(pointSize.Width / -2f, pointSize.Height / -2f);
 
            childElement.BackgroundShape?.Paint((Graphics)radGraphics.UnderlayGraphics, pointRect);
 
            GraphicsPath pointPath;
 
            if (childElement.Shape != null)
            {
                pointPath = childElement.Shape.CreatePath(pointRect);
            }
            else
            {
                pointPath = new GraphicsPath();
                pointPath.AddEllipse(pointRect);
            }
 
            if (pointPath != null)
            {
                var pointFill = new FillPrimitiveImpl(childElement, null);
 
                pointFill.PaintFill(radGraphics, pointPath, pointRect);
 
                var pointBorder = new BorderPrimitiveImpl(childElement, null);
 
                pointBorder.PaintBorder(radGraphics, null, pointPath, pointRect);
 
                if (childElement.Image != null)
                {
                    var pointImage = new ImagePrimitiveImpl(childElement);
 
                    pointImage.PaintImage(
                        radGraphics,
                        childElement.Image,
                        pointRect,
                        childElement.ImageLayout,
                        childElement.ImageAlignment,
                        childElement.ImageOpacity,
                        false);
                }
 
                pointPath.Dispose();
            }
        }
    }
 
    private static void ChangePointStyle(DataPointElement pointElement, out SizeF pointSize)
    {
        switch (pointElement.DataPoint.DataItem)
        {
            case MyData myData when myData.Value >= 30:
                pointElement.BackColor = ColorTranslator.FromHtml("#981B1B");
                pointSize = new SizeF(pointElement.PointSize.Width * 1.2f, pointElement.PointSize.Height * 1.2f);
 
                break;
 
            default:
                pointSize = pointElement.PointSize;
                break;
        }
    }
}
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 22 Jan 2021, 02:16 PM

Hello, Johnny,

I am glad that you have found a suitable solution for your requirement using the custom LineSeriesDrawPart that was previously suggested.

Feel free to use it if it produces the desired style.

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

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