Reputation: 93
I'm working on a Blazor project, but my problem is C#. I do understand the problem, but I just can not solve it in the Blazor context.
In my razor page I use a blazorise linechart that takes dates for the x-axis. That works perfectly well if I use non-dynamic dates. The
<LineChart @ref="lineChart" TItem="double" OptionsObject="@options"/>
However, to determine the dates (so the x-axis labels) dynamically, I need the following code behind:
public partial class ChartComponent : ComponentBase
{
[Parameter]
public List<Observation> Observations { get; set; } //an Observation has a field with a Date in it.
Object options = new
{
Scales = new
{
XAxes = new[]
{
new
{
labels = new[]{GetDateTimeLabels()} //this gets me the error, if I use new[]{DateTime.Now,...,DateTime.Now+n} it works just fine.
}
}
}
};
public DateTime[] GetDateTimeLabels()
{
DateTime[] dateLabels = VACRAObservations.Select(x => x.Date).ToArray();
return dateLabels;
}
This gets me an error "a field initializer cannot reference the non-static field method or property", which I understand, because the compiler does not know if GetLabels() is ready before Object options is initialized.
I cannot go around the [Parameter], I need it to get the list of Observations into the razor page.
I tried to put it all in the constructor, but the constructor is initialized before the parameter is taken in.
I tried to do it with statics, but a static class can not derive from Componentbase class.
I'm at a loss what to do. Please let me know if you need more information.
Upvotes: 0
Views: 1266
Reputation: 93
Thanks to Henk en enet:
<LineChart @ref="lineChart" TItem="double" OptionsObject="@Options"/>
And this is the working partial class
public partial class xxxComponent : ComponentBase
{
public void Refresh()
{
StateHasChanged();
}
[Parameter]
public List<Observation> Observations { get; set; }
Object Options =>
new
{
Scales = new
{
XAxes = new[]
{
new
{
labels = GetDateTimeLabels() //changed to avoid a 2 dimensional array
}
}
}
};
LineChart<double> lineChart;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await HandleRedraw();
}
}
async Task HandleRedraw()
{
await lineChart.Clear();
await lineChart.AddDataSet(GetLineChartDataset());
await lineChart.Update();
}
LineChartDataset<double> GetLineChartDataset()
{
return new LineChartDataset<double>
{
Label = "VA",
Data = GetVALevels(),
Fill = false,
PointRadius = 2,
BorderDash = new List<int> { },
};
}
public DateTime[] GetDateTimeLabels()
{
DateTime[] dateLabels = Observations.Select(x => x.Date).ToArray();
return dateLabels;
}
public List<double> GetVALevels()
{
List<double> vALevels = Observations.Select(x => x.VA).ToList();
return vALevels;
}
}```
Upvotes: 0
Reputation: 273864
The easiest fix is to make it a property. When you only need it once, add a >
:
Object options => new { ... };
and when you need to guard against evaluating it too often:
Object _options = null;
Object options => _options ?? (_options = new
{
... // as before
});
Upvotes: 1