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

CartesianGridLineAnnotation with vertical label

4 Answers 186 Views
ChartView
This is a migrated thread and some comments may be shown as answers.
Holger
Top achievements
Rank 1
Holger asked on 31 Mar 2019, 07:31 PM

     Hi, is there a way to control the orientation of Labels in CartesianGridLineAnnotation?

To avoid overlapping I would like to have a vertical label on a vertical line, which looks to me like better visual design.

But I haven't found any properties to Control simple things like orientation.

4 Answers, 1 is accepted

Sort by
0
Dess | Tech Support Engineer, Principal
Telerik team
answered on 02 Apr 2019, 01:16 PM
Hello, Holger,   

You can control how the label of the CartesianGridLineAnnotation is oriented by using a custom CartesianGridLineAnnotationDrawPart. You can find below a sample code snippet demonstrating how to achieve the illustrated behavior:

public RadForm1()
{
    InitializeComponent();
 
    this.radChartView1.CreateRenderer += radChartView1_CreateRenderer;
 
    ScatterLineSeries scatterSeries = new ScatterLineSeries();
    scatterSeries.DataPoints.Add(new ScatterDataPoint(15, 19));
    scatterSeries.DataPoints.Add(new ScatterDataPoint(18, 10));
    scatterSeries.DataPoints.Add(new ScatterDataPoint(13, 15));
    scatterSeries.DataPoints.Add(new ScatterDataPoint(10, 8));
    scatterSeries.DataPoints.Add(new ScatterDataPoint(5, 2));
    scatterSeries.PointSize = new SizeF(8, 8);
    this.radChartView1.Series.Add(scatterSeries);
    ScatterLineSeries scatterSeries2 = new ScatterLineSeries();
    scatterSeries2.DataPoints.Add(new ScatterDataPoint(2, 24));
    scatterSeries2.DataPoints.Add(new ScatterDataPoint(7, 12));
    scatterSeries2.DataPoints.Add(new ScatterDataPoint(15, 10));
    scatterSeries2.DataPoints.Add(new ScatterDataPoint(18, 22));
    scatterSeries2.DataPoints.Add(new ScatterDataPoint(20, 20));
    scatterSeries2.Shape = new RoundRectShape(1);
    scatterSeries2.PointSize = new SizeF(8, 8);
    this.radChartView1.Series.Add(scatterSeries2);
     
    CartesianGridLineAnnotation annotation1 = new CartesianGridLineAnnotation();
    annotation1.Axis = this.radChartView1.Axes[0] as CartesianAxis;
    annotation1.Value = 5.8;
    annotation1.Label = "Some text";
     
    annotation1.BorderColor = Color.Red;
    annotation1.BorderDashStyle = DashStyle.Solid;
    annotation1.BorderWidth = 1;
    this.radChartView1.Annotations.Add(annotation1);
}
 
private void radChartView1_CreateRenderer(object sender, ChartViewCreateRendererEventArgs e)
{
    e.Renderer = new CustomRenderer(e.Area as CartesianArea);
}
 
public class CustomRenderer : CartesianRenderer
{
    public CustomRenderer(CartesianArea area) : base(area)
    {
    }
 
    protected override void InitializeAnnotations(AnnotationDrawMode drawMode)
    {
        for (int i = 0; i < this.Area.Annotations.Count; i++)
        {
            if (this.Area.Annotations[i] is CartesianGridLineAnnotation)
            {
                this.DrawParts.Add(new CustomCartesianGridLineAnnotationDrawPart(this.Area.Annotations[i] as CartesianGridLineAnnotation, this));
            }
        }
    }
}
 
public class CustomCartesianGridLineAnnotationDrawPart : CartesianGridLineAnnotationDrawPart
{
    public CustomCartesianGridLineAnnotationDrawPart(CartesianGridLineAnnotation element, CartesianRenderer renderer) : base(element, renderer)
    {
    }
 
    public override void Draw()
    {
        FieldInfo fi = typeof(CartesianGridLineAnnotation).GetField("model", BindingFlags.Instance | BindingFlags.NonPublic);
        ChartAnnotationModel model = fi.GetValue(this.Element) as ChartAnnotationModel;
        RectangleF rect = ChartRenderer.ToRectangleF(model.LayoutSlot);
        rect.Offset(this.ViewportOffsetX, this.ViewportOffsetY);
 
        Graphics graphics = this.Renderer.Surface as Graphics;
        RadGdiGraphics radGraphics = new RadGdiGraphics(graphics);
 
        Rectangle clipRect = ChartRenderer.ToRectangle(this.Element.View.GetArea<CartesianArea>().AreaModel.PlotArea.LayoutSlot);
        clipRect.Offset((int)this.ViewportOffsetX, (int)this.ViewportOffsetY);
        graphics.SetClip(clipRect);
 
        GraphicsPath path = new GraphicsPath();
        path.AddLine(rect.Location, new PointF(rect.Right, rect.Bottom));
 
        BorderPrimitiveImpl border = new BorderPrimitiveImpl(this.Element, null);
        border.PaintBorder(radGraphics, null, path, rect);
 
        rect.Size = graphics.MeasureString(this.Element.Label, this.Element.Font);
        rect.Offset(this.Element.PositonOffset.Width + 1, this.Element.PositonOffset.Height + 1);
 
        TextParams tp = new TextParams();
        tp.textOrientation = Orientation.Vertical;
        tp.font = this.Element.Font;
        tp.foreColor = this.Element.ForeColor;
        tp.paintingRectangle = new RectangleF(rect.X, rect.Y, rect.Height, rect.Width);
        tp.text = this.Element.Label;
  
        FillPrimitiveImpl fill = new FillPrimitiveImpl(this.Element, null);
        fill.PaintFill(radGraphics, null, rect);
 
        radGraphics.DrawString(tp, new SizeF(rect.Height, rect.Width));
    }
}


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
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Holger
Top achievements
Rank 1
answered on 04 Apr 2019, 06:55 AM

well, thank you.
I understand the idea and the concept, but it doesn't work, and I'm wondered why it worked on your side.

The order of execution is kind of wrong.
In the line radChartView1.Series.Add(scatterSeries2);
the CreateRenderer event is already invoked, it tries to measures some label or so, 

there are about 20 levels of function calls on the call-stack all internal Telerik code.

At this point in time, the annotations arent' created, but the InitializeAnnotation is also called immediatly in the constructor of the Renderer.

It tried to add the series later, but this doesn't work, since the axis is not created, before the serious is added.

I have a barseries, instead of a scatter, but I guess this will not make the difference.
However, there is a problem with the order of commands and events.

Probably the Drawpart has to be added at another place (another time).

something like radchartview.Area.Renderer exists, but is not public accessible.

0
Accepted
Dess | Tech Support Engineer, Principal
Telerik team
answered on 04 Apr 2019, 11:19 AM
Hello, Holger,    

It is necessary to subscribe to the CreateRenderer event before populating RadChartView. Thus, we will ensure that the custom rendering for the annotation and its label will be performed. I have attached my sample project for your reference. Could you please give it a try on your end and see how it works? 

Should you have further questions please let me know.

 Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik
Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Holger
Top achievements
Rank 1
answered on 04 Apr 2019, 01:19 PM

Well I found it.

This "InitializeAnnotations" is called 4 times.

The first 2 times there are no existing annotations, I had a crash, while your kind of stated "if an annotation exists than ..."

But since the method is called twice with annotations, there are 2 drawparts created for the same element (also in your sample).

It doesn't seem to disturb the layout logic, it's just probably not the perfect way as DrawParts should be used.

I would expect, adding multiple Drawparts for the same Element causes exceptions; well it didn't.

 

However, your support compensates the leak of documentation.

Just by reading documentation you never get the approch of accessing private Properties via Reflection and stuff like this.

 

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