Page 1 of 1
TeeChart .NET For Blazor NullReferenceException
Posted: Thu Jul 25, 2024 6:57 pm
by 15695569
Hi,
I am attempting to draw rectangles on the point chart in the .NET 8 blazor example program and getting a null reference exception when trying to call Graphics3DImageSharp.Rectangle(Rectangle rectangle).
Here is a copy of the stack trace.
at SixLabors.ImageSharp.GraphicOptionsDefaultsExtensions.GetGraphicsOptions(IImageProcessingContext context)
at SixLabors.ImageSharp.Drawing.Processing.DrawingOptionsDefaultsExtensions.GetDrawingOptions(IImageProcessingContext context)
at SixLabors.ImageSharp.Drawing.Processing.FillPathExtensions.Fill(IImageProcessingContext source, IBrush brush, IPath path)
at Steema.TeeChart.Drawing.Graphics3DImageSharp.Rectangle(Rectangle r)
at TeeChartOnBlazor.Pages.GetGeneralChart.DrawRectangle(Graphics3DBase graphics, Rectangle rect, Int32 cornerRadius) in C:\Git\TeeChartOnBlazor\TeeChart-NET-Pro-Samples\Blazor\NET 8\TeeChartOnBlazor\Pages\GetGeneralChart.razor:line 326
Thanks,
Jeff
Re: TeeChart .NET For Blazor NullReferenceException
Posted: Fri Jul 26, 2024 2:21 pm
by edu
Hello Jeff,
Thank you for reporting this issue to us. To assist you more effectively, could you please provide the specific code you're working with? More specifically, how or where you're calling the function or drawing the rectangle, as we can't seem to replicate the null reference exception you're encountering. This information will help us better understand the situation and provide you with more accurate guidance or troubleshooting steps, or fixing the bug on our end if that's the case.
We appreciate your cooperation and look forward to resolving this issue for you.
Thanks again,
Best regards,
Edu
Re: TeeChart .NET For Blazor NullReferenceException
Posted: Tue Jul 30, 2024 2:15 pm
by 15695569
Hello Edu,
Here is a sample of the code.
Code: Select all
protected override async Task OnInitializedAsync()
{
int chartType = Convert.ToInt32(CType);
if ((chartType == 31) || (chartType == 32)) //pie, donut
{
GetGeneralChart cGen = new GetGeneralChart();
[b] chartJS = await cGen.GetJSChart(chartType, 1400, 500);[/b]
chartName = cGen.chartName;
chartCode = cGen.getFormattedCode();
title = cGen.title;
supportUnit = "<script src=\"js/pieplus.js\" type=\"text/javascript\"></script>";
}
else if (chartType == 101) //appointments, advanced chart
{
//title
string aTitle = "Appointments";
//Year labels
string[] xLabels = new string[] { "2019", "2020", "2021", "2022", "2023" };
//Series names
string[] sNames = new string[] { "Ancillaries", "Core staff" };
//Chart data
double?[,] apptData = new double?[,] {
{ /*Ancillaries*/ 10,12,31,34,16 },
{ /*Core*/ 5,7,12,12,3 }};
MultiBars stack = MultiBars.Stacked;
int incr = 5; //left axis increment
ChartTable cGen = new ChartTable();
chartJS = await cGen.loadAppointmentsChart(aTitle, sNames, apptData,
stack, xLabels, newLineLabel(xLabels),
incr);
title = aTitle;
//Make the sourcecode reference page.
chartCode = "\n<h3>Setup data</h3>";
chartCode += getAppointmentsCode();
chartCode += "\n<h3>Chart generation</h3>";
chartCode += cGen.getChartCode();
chartCode += "\n<h3>Javascript Legend code</h3>";
chartCode += cGen.getJSCode();
supportUnit = "<script src=\"js/appointment.js\" type=\"text/javascript\"></script>";
}
else //if (chartType < 30) //general charts
{
GetGeneralChart cGen = new GetGeneralChart();
chartJS = await cGen.GetJSChart(chartType, 1400, 500);
chartName = cGen.chartName;
chartCode = cGen.getFormattedCode();
if ((chartType == 34) || (chartType == 33)) //custom gauge
{
supportUnit = "<script src=\"js/gauge.js\" type=\"text/javascript\"></script>";
if (chartType == 34)
title = "VU Meter - analogue type";
}
else
{
supportUnit = "<script src=\"js/stdsetup.js\" type=\"text/javascript\"></script>";
title = cGen.title;
}
}
chartResize = "<script> function resizeChart() { resizeC(" + chartName + "); } </script>";
}
public Task<string> GetJSChart(int chartType, int width, int height)
{
Steema.TeeChart.TChart mChart = new TChart();
bool animate = false;
switch (chartType) {
case 0: Line line = new Line(mChart.Chart);
animate=true;
break;
case 1: Points points = new Points(mChart.Chart);
animate=true;
break;
case 2: Area area1 = new Area(mChart.Chart);
Area area2 = new Area(mChart.Chart);
//countSeries = 2;
animate = true;
break;
case 3: break;
case 5: Bubble bubble = new Bubble(mChart.Chart); animate = true; break;
case 6: Candle candle = new Candle(mChart.Chart); break;
case 7: Gantt gantt = new Gantt(mChart.Chart);
break;
case 31: Pie pie = new Pie(mChart.Chart); break;
case 32: Donut donut = new Donut(mChart.Chart); break;
case 33:
case 34: CircularGauge cGauge = new CircularGauge(mChart.Chart); break;
}
var series = mChart.Series[0];
mChart.Header.Text = ""; // series.Description + " series";
mChart.Axes.Left.Title.Text = "value";
foreach (Series s in mChart.Series)
{
if (series.GetType() == typeof(Bubble))
{
((Bubble)(s)).Pointer.Gradient.Visible = true;
((Bubble)(s)).Pointer.Pen.Visible = false;
s.FillSampleValues(50);
}
else if ((series.GetType() == typeof(Gantt)))
s.FillSampleValues(9);
else
s.FillSampleValues();
}
if (mChart.Series.Count > 1)
{
if (mChart[0].MaxYValue() > mChart[1].MaxYValue())
mChart.Axes.Left.SetMinMax(0, mChart[0].MaxYValue()+20);
else
mChart.Axes.Left.SetMinMax(0, mChart[1].MaxYValue()+20);
}
Graphics3DBase graphics = mChart.Graphics3D;
ChartBrush brush = null;
ChartPen pen = null;
graphics.Brush = null;
graphics.Pen = null;
Brush = new ChartBrush(mChart.Chart);
Pen = new ChartPen(mChart.Chart);
try
{
if (Brush != null)
{
graphics.Brush = Brush;
graphics.Brush.Chart = mChart.Chart;
}
if (Pen != null)
{
graphics.Pen = Pen;
graphics.Pen.Chart = mChart.Chart;
}
var dataSet = series.YValues.Value;
int counter = 0;
foreach (int value in dataSet)
{
Random rndX = new Random();
Random rndY = new Random();
Rectangle rect = new Rectangle(counter, value, rndX.Next(0, 99), rndY.Next(0, 99));
Rectangle bounds = new Rectangle(0, 0, 900, 300);
// Draw the point.
[b]DrawWrappedRectangle(graphics, rect, bounds);[/b]
}
}
finally
{
brush?.Dispose();
pen?.Dispose();
graphics.Brush = null;
graphics.Pen = null;
}
series.XValues.DateTime = true;
//mChart.Axes.Bottom.Labels.Angle = 90;
//mChart.Axes.Bottom.Increment = Steema.TeeChart.Utils.GetDateTimeStep(DateTimeSteps.OneDay);
//mChart.Axes.Left.Title.Text = "µVal";
if ((mChart.Series.Count == 1) && (series.GetType() != typeof(Gantt)))
mChart.Axes.Left.SetMinMax(series.YValues.Minimum - 10, series.YValues.Maximum + 10);
chartName = "dynoTeeChart";
mChart.Export.Image.JScript.ChartName = chartName;
MemoryStream ms = new MemoryStream();
mChart.Export.Image.JScript.Width = width;
mChart.Export.Image.JScript.Height = height;
mChart.Export.Image.JScript.DoFullPage = false; //inline, no page <html> header tags
if ((series.GetType() == typeof(Pie)) ||
(series.GetType() == typeof(Donut)))
{
series.Marks.Visible = true;
series.Marks.Arrow.Visible = false;
series.Marks.Arrow.Color = Color.White;
series.Marks.Transparent = true;
series.Marks.Pen.Transparency = 100;
series.Marks.Pen.Color = Color.White;
series.Marks.Font.Color = Color.White;
mChart.Export.Image.JScript.CustomCode = getCustomCodeOp2(mChart);
}
else
mChart.Export.Image.JScript.CustomCode = getCustomCode1(animate, mChart);
if ((series.GetType() == typeof(Gantt)))
{
((Gantt)series).Brush.Gradient.Visible = false;
((Gantt)series).NextTasks[0] = 6;
mChart.Axes.Left.Title.Text = "task";
}
if ((series.GetType() == typeof(CircularGauge)))
{
mChart.Axes.Left.Title.Text = "µHz";
var customCode = new List<string>();
if (chartType == 34)
{
customCode.Add("modGauge(" + chartName + ", " + chartName + ".series.items[0]" + ");");
customCode.Add("setTimeout(modVal, 500);");
}
else
{
((CircularGauge)(mChart[0])).Value = 0;
customCode.Add(chartName + ".series.items[0]" + ".format.shadow.visible=false;");
customCode.Add(chartName + ".series.items[0]" + ".back.visible=false;");
customCode.Add("growVal(" + chartName + ");");
customCode.Add("setTimeout(growVal, 500);");
}
mChart.Export.Image.JScript.CustomCode = customCode.ToArray();
}
title = mChart.Series[0].Description;
mChart.Export.Image.JScript.Save(ms);
ms.Position = 0;
StreamReader reader = new StreamReader(ms);
//setup our chart name, here 'dynoChartName'.
string result = "<script> var " + chartName + "; " + reader.ReadToEnd() + "</script>";
return Task.FromResult(result);
}
/// <summary>
/// Draws a rectangle that may wrap around the axes.
/// </summary>
/// <param name="graphics">The graphics.</param>
/// <param name="rect">The rectangle.</param>
/// <param name="bounds">The boundary over which the rectangle may wrap.</param>
/// <param name="cornerRadius">[Optional] The radius of the rounded corners, in pixels.</param>
/// <exception cref="ArgumentNullException">Thrown if <paramref name="graphics"/> is <b>null</b>.</exception>
public static void DrawWrappedRectangle(Graphics3DBase graphics, Rectangle rect, Rectangle bounds, int cornerRadius = 0)
{
if (graphics == null)
{
throw new ArgumentNullException(nameof(graphics));
}
[b]DrawRectangle(graphics, rect, cornerRadius);[/b]
}
/// <summary>
/// Draws a rectangle.
/// </summary>
/// <param name="graphics">The graphics.</param>
/// <param name="rect">The rectangle.</param>
/// <param name="cornerRadius">[Optional] The radius of the rounded corners, in pixels.</param>
public static void DrawRectangle(Graphics3DBase graphics, Rectangle rect, int cornerRadius = 0)
{
if (cornerRadius == 0)
{
try
{
[b]graphics.Rectangle(rect);[/b]
}
catch (Exception ex)
{
String message = ex.Message;
throw ex;
}
}
else if (cornerRadius > Math.Max(rect.Width, rect.Height) / 2)
{
graphics.Ellipse(rect);
}
else
{
graphics.RoundRectangle(rect, cornerRadius);
}
}
I bolded each line that is calling the next method. If there is a way I can send you the zipped project please let me know as the forum is saying the file size is too large.
Thanks,
Jeff
Re: TeeChart .NET For Blazor NullReferenceException
Posted: Thu Aug 01, 2024 10:44 am
by edu
Hello Jeff:
Thank you for providing the code snippet.
We were able to spot the issue you're encountering.
Adding this code after the line ..
Code: Select all
customCode.Add(" drawAppointments(" + chartAppointm.Export.Image.JScript.ChartName + ", " + labelLines + ");");
.. should achieve what you're trying to make (drawing a rectangle)
Code: Select all
customCode.Add($"let myFormat = new Tee.Format({chartAppointm.Export.Image.JScript.ChartName});");
customCode.Add("myFormat.gradient.visible=true;");
customCode.Add("myFormat.gradient.colors=[\"white\",\"lime\"];");
customCode.Add("myFormat.transparency=0.3;");
customCode.Add($"{chartAppointm.Export.Image.JScript.ChartName}.ondraw=function()");
customCode.Add("{");
customCode.Add($"var x1 = {chartAppointm.Export.Image.JScript.ChartName}.axes.bottom.calc(4),");
customCode.Add($"y1 = {chartAppointm.Export.Image.JScript.ChartName}.axes.left.calc(70),");
customCode.Add($"x2 = {chartAppointm.Export.Image.JScript.ChartName}.axes.bottom.calc(7),");
customCode.Add($"y2 = {chartAppointm.Export.Image.JScript.ChartName}.axes.left.calc(40);");
customCode.Add("// X,Y, Width, Height");
customCode.Add("myFormat.rectangle(x1,y1, x2-x1, y2-y1);");
customCode.Add("}");
Here you can see the rectangle with color 'White, Lime' (top right)
- aaDrawRectangleExample.png (24.54 KiB) Viewed 30651 times
There are complications with drawing a rectangle using the method you were trying to use due to the nature of how Graphics3DImageSharp works (because the chart is not yet drawn ..)
Since there's the conversion to js, custom drawing code should be written on your
customCode
string list instead.
If there's anything else you may need or any other questions, please let us know
Regards,
Edu
Re: TeeChart .NET For Blazor NullReferenceException
Posted: Fri Aug 02, 2024 9:17 pm
by 15695569
Hi Edu,
I got the drawing working on the appointments chart in the sample project. I am trying to draw a box around every data point in the point chart but am getting a blank chart back. Here is the method where I added the custom code.
//general type characteristics
string[] getCustomCode1(bool animate, TChart aChart, double[] dataSet)
{
var customCode = new List<string>();
if (animate)
{
if (aChart[0].GetType() == typeof(Area))
{
customCode.Add(" //animation");
customCode.Add(" animation = new Tee.SeriesAnimation();");
customCode.Add(" animation.duration = 1700;");
customCode.Add(" animation.kind = \"all\";");
customCode.Add(" animation.mode = \"linear\";");
}
else
{
customCode.Add(" //animation");
customCode.Add(" animation = new Tee.SeriesAnimation();");
customCode.Add(" animation.duration = 900;");
customCode.Add(" animation.kind = \"each\";");
customCode.Add(" fadeAnimation = new Tee.FadeAnimation();");
customCode.Add(" fadeAnimation.duration = 500;");
customCode.Add(" fadeAnimation.fade.series = true;");
customCode.Add(" fadeAnimation.fade.marks = true;");
customCode.Add(" animation.mode = \"linear\"; ");
customCode.Add(" fadeAnimation.mode = \"linear\";");
customCode.Add(" animation.items.push(fadeAnimation);");
customCode.Add(" ");
}
customCode.Add(" animation.animate(" + aChart.Export.Image.JScript.ChartName + ");");
}
if (aChart[0].GetType() == typeof(Candle))
{
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.datetime = true;");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.labels.dateFormat = \"shortDate\";");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".series.items[0].dateFormat = \"shortDate\";");
//cursortool
customCode.Add("var t = new Tee.CursorTool(" + aChart.Export.Image.JScript.ChartName + ");");
customCode.Add("t.direction = \"both\";");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".tools.add(t);");
}
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.labels.format.font.fill = \"rgba(0,0,0,0.6)\";");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.labels.format.font.setSize(\"10px\");");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".series.items[0].marks.transparent = true;");
//customCode.Add("hostChart = " + aChart.Export.Image.JScript.ChartName + ";");
customCode.Add("chartFeatures(" + chartName + ");"); //call general setup enhancements
customCode.Add("resizeC(" + chartName + ");");
if (aChart[0].GetType() == typeof(Steema.TeeChart.Styles.Points))
{
int counter = 0;
foreach (int value in dataSet)
{
Random rndX = new Random();
Random rndY = new Random();
Rectangle rect = new Rectangle(counter, value, rndX.Next(0, 99), rndY.Next(0, 99));
Rectangle bounds = new Rectangle(0, 0, 900, 300);
customCode.Add($"let myFormat = new Tee.Format({aChart.Export.Image.JScript.ChartName});");
customCode.Add("myFormat.gradient.visible=true;");
customCode.Add("myFormat.gradient.colors=[\"white\",\"lime\"];");
customCode.Add("myFormat.transparency=0.3;");
customCode.Add($"{aChart.Export.Image.JScript.ChartName}.ondraw=function()");
customCode.Add("{");
customCode.Add($"var x1 = {aChart.Export.Image.JScript.ChartName}.axes.bottom.calc(1),");
customCode.Add($"y1 = {aChart.Export.Image.JScript.ChartName}.axes.left.calc(1),");
customCode.Add($"x2 = {aChart.Export.Image.JScript.ChartName}.axes.bottom.calc(100),");
customCode.Add($"y2 = {aChart.Export.Image.JScript.ChartName}.axes.left.calc(100);");
customCode.Add("// X,Y, Width, Height");
customCode.Add("myFormat.rectangle(x1,y1, x2-x1, y2-y1);");
customCode.Add("}");
counter++;
}
}
return customCode.ToArray();
}
Thanks,
Jeff
Re: TeeChart .NET For Blazor NullReferenceException
Posted: Mon Aug 05, 2024 2:42 pm
by edu
Hello Jeff:
I made some changes to the code you provided to avoid js errors that were happening.
Separating variable declarations and the onDraw from the loop is what I feel is the most important 'change', but I recommend you to take a look at the whole function regardless.
This is just an interpretation of what you said here ...
I am trying to draw a box around every data point in the point chart but am getting a blank chart back.
... so please if you would like the end result to be a bit different, adjust the necessary code to better match your desired result
This is how the result looks like:
- Screenshot 2024-08-05 163927.png (47.78 KiB) Viewed 29982 times
and this is how the code looks like:
Code: Select all
string[] getCustomCode1(bool animate, TChart aChart, double[] dataSet)
{
var customCode = new List<string>();
if (animate)
{
if (aChart[0].GetType() == typeof(Area))
{
customCode.Add(" //animation");
customCode.Add(" animation = new Tee.SeriesAnimation();");
customCode.Add(" animation.duration = 1700;");
customCode.Add(" animation.kind = \"all\";");
customCode.Add(" animation.mode = \"linear\";");
}
else
{
customCode.Add(" //animation");
customCode.Add(" animation = new Tee.SeriesAnimation();");
customCode.Add(" animation.duration = 900;");
customCode.Add(" animation.kind = \"each\";");
customCode.Add(" fadeAnimation = new Tee.FadeAnimation();");
customCode.Add(" fadeAnimation.duration = 500;");
customCode.Add(" fadeAnimation.fade.series = true;");
customCode.Add(" fadeAnimation.fade.marks = true;");
customCode.Add(" animation.mode = \"linear\"; ");
customCode.Add(" fadeAnimation.mode = \"linear\";");
customCode.Add(" animation.items.push(fadeAnimation);");
customCode.Add(" ");
}
customCode.Add(" animation.animate(" + aChart.Export.Image.JScript.ChartName + ");");
}
if (aChart[0].GetType() == typeof(Candle))
{
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.datetime = true;");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.labels.dateFormat = \"shortDate\";");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".series.items[0].dateFormat = \"shortDate\";");
//cursortool
customCode.Add("var t = new Tee.CursorTool(" + aChart.Export.Image.JScript.ChartName + ");");
customCode.Add("t.direction = \"both\";");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".tools.add(t);");
}
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.labels.format.font.fill = \"rgba(0,0,0,0.6)\";");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".axes.bottom.labels.format.font.setSize(\"10px\");");
customCode.Add(aChart.Export.Image.JScript.ChartName + ".series.items[0].marks.transparent = true;");
//customCode.Add("hostChart = " + aChart.Export.Image.JScript.ChartName + ";");
customCode.Add("chartFeatures(" + chartName + ");"); //call general setup enhancements
customCode.Add("resizeC(" + chartName + ");");
if (aChart[0].GetType() == typeof(Steema.TeeChart.Styles.Points))
{
int counter = 0;
Random rndX = new Random();
Random rndY = new Random();
customCode.Add($"const myFormat = new Tee.Format({aChart.Export.Image.JScript.ChartName});");
customCode.Add("myFormat.gradient.visible=true;");
customCode.Add("myFormat.gradient.colors=[\"white\",\"lime\"];");
customCode.Add("myFormat.transparency=0.3;");
customCode.Add("let axisX1, axisY1, axisX2, axisY2;");
customCode.Add($"{aChart.Export.Image.JScript.ChartName}.ondraw = function()");
customCode.Add("{");
foreach (int value in dataSet)
{
// Rectangle rect = new Rectangle(counter, value, rndX.Next(0, 99), rndY.Next(0, 99));
// Rectangle bounds = new Rectangle(0, 0, 900, 300);
customCode.Add($"axisX1 = {aChart.Export.Image.JScript.ChartName}.axes.bottom.calc({counter});");
customCode.Add($"axisY1 = {aChart.Export.Image.JScript.ChartName}.axes.left.calc({value});");
customCode.Add($"axisX2 = {aChart.Export.Image.JScript.ChartName}.axes.bottom.calc({rndX.Next(0, 99)});");
customCode.Add($"axisY2 = {aChart.Export.Image.JScript.ChartName}.axes.left.calc({rndX.Next(0, 99)});");
customCode.Add("// X,Y, Width, Height");
customCode.Add("myFormat.rectangle(axisX1 + 5, axisY1 + 5, 20, 20);");
counter++;
}
customCode.Add("}");
}
return customCode.ToArray();
}
If there's anything else we can help with, please let us know.
Regards,
Edu