Hello. I'm having trouble with a specific observable data collection. For some reason, when data is changed, the grid fails to update. Interestingly, when data is added or removed, the data is properly updated. Weirdest thing is that this was working perfectly until this week. Can't figure out why for the life of me. Thanks.
@page "/fetchDataObv"
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Buttons
@using PowerBlazor.Data
@using System.Dynamic
@using System.Collections.ObjectModel
@using System.ComponentModel
@using System.Security.Cryptography.X509Certificates
@using System.Threading
@using Syncfusion.Blazor.Charts.BulletChart.Internal
@using Syncfusion.Blazor.PivotView.Internal
@using SelectionType = Syncfusion.Blazor.Grids.SelectionType
@inject Data.WeatherForecastService _foreCastService
@inject IJSRuntime JSRuntime
@*needed to run the JS runtime obviously>*@
<div class="heading">
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
</div>
@if (GridData == null)
{
<p><em>Loading...</em></p>
}
else
{
<input type="text" @bind="temperatureCelEdit" />
<input type="text" @bind="summaryEdit" />
<SfButton ID="add" @onclick="AddData">Add Data</SfButton>
<SfButton ID="del" @onclick="DeleteData">Delete Data</SfButton>
<SfButton ID="update" @onclick="ChangeData">Update Data</SfButton>
<SfGrid @ref="gridReference" AllowSelection="true" DataSource="@GridData" AllowPaging="true" AllowSorting="true">
<!--Allow paging puts data in pages--->
<!--Allow sorting allows for.... sorting--->
<!--Filtering allows user to search within the table, customizing this say to only apply to a specific field requires a seperate function. See documentation.--->
<!--Grouping allows user to drag and drop the table/remove items--->
<GridPageSettings PageSize="20"></GridPageSettings>
<GridEditSettings AllowAdding="true" AllowDeleting="true"></GridEditSettings>
<GridSelectionSettings Type="SelectionType.Multiple"></GridSelectionSettings> <!---Selection type multiple allows you to select multiple grids-->
<GridEvents QueryCellInfo="CellInfoHandler" TValue="WeatherForecast"></GridEvents>
<GridColumns>
<!--Notice the nameof field refers to the class within the data set, not the data set itself--->
<GridColumn Field=@nameof(WeatherForecast.Date) HeaderText="Custom Date" AllowSorting="true"></GridColumn> <!--HeaderText allows for custom fields, if left empty these will be autofilled based on the variables in the class--->
<GridColumn Field=@nameof(WeatherForecast.TemperatureC) HeaderText="Custom Temp C"></GridColumn>
<GridColumn Field=@nameof(WeatherForecast.TemperatureF) Format="N2" HeaderText="Custom Temp F"></GridColumn>
<GridColumn Field=@nameof(WeatherForecast.Summary) HeaderText="Custom Summary"></GridColumn>
<GridColumn Field=@nameof(WeatherForecast.lastUpated) HeaderText="Custom Summary"></GridColumn>
</GridColumns>
</SfGrid>
<style>
.below{
background-color: #5c92f7;
}
.above{
background-color: #e3b024;
}
</style>
}
@code {
public SfGrid<WeatherForecast> gridReference;
private Timer aTimer;
private Random rng = new Random();
public ObservableCollection<Data.WeatherForecast> GridData { get; set; }
private int temperatureCelEdit { get; set; }
private string summaryEdit { get; set; }
public void AddData()
{
GridData.Add(new WeatherForecast() { Date = DateTime.Now, TemperatureC = temperatureCelEdit, Summary = summaryEdit, });
}
public void DeleteData()
{
GridData.Remove(GridData.First());
}
public void ChangeData()
{
@*Test to change data *@
var currentSet = GridData.First();
}
protected override async void OnInitialized()
{
var data = await _foreCastService.GetForecastAsync(DateTime.Now);
GridData = new ObservableCollection<WeatherForecast>(data);
aTimer = new Timer(
delegate (object state)
{
UpdateRandomRow();
},
null,
TimeSpan.Zero,
TimeSpan.FromSeconds(.5)
);
}
private async void unSelect(int idx) //async functions for the delay
{
await Task.Delay(1000);
await JSRuntime.InvokeAsync<object>("unApplycolor", idx); // runs JS file
}
private void UpdateRandomRow()
{
// 1. Pick a random row.
var idx = new Random().Next(0, GridData.Count);
// 2. Update its value randomly.
var row = GridData[idx];
row.TemperatureC = rng.Next(-20, 55);
row.lastUpated = DateTime.Now;
idx = idx - ((gridReference.PageSettings.CurrentPage - 1) * gridReference.PageSettings.PageSize); //only required for paging, needed to adjust index to page
//runs JS to change color
JSRuntime.InvokeAsync<object>("applycolor", idx);
unSelect(idx);
}
public void CellInfoHandler(QueryCellInfoEventArgs<WeatherForecast> Args)
{
if (Args.Column.Field == "TemperatureC")
{
if (Args.Data.TemperatureC < 0)
{
Args.Cell.AddClass(new string[] {"below"});
}
else
{
Args.Cell.AddClass(new string[] { "above" });
}
}
}
}
using System;
using System.ComponentModel;
using System.Dynamic;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Threading;
namespace PowerBlazor.Data
{
public class WeatherForecast : INotifyPropertyChanged
{
public DateTime Date { get; set; }
public DateTime lastUpated { get; set; } //last updated event
public int TemperatureC { get; set; }
public float TemperatureF => 32 + (TemperatureC / 0.5556f);
public string Summary { get; set; }
/*private static int newTemps()
{
//takes up space so this should probably be moved to an external function or just edit C and F directly
Random rng = new Random();
return rng.Next(-20, 55);
}*/
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
I have a class that generates the WeatherForecast objects, and it hasn't been changed since last week.