I am experiencing some unexpected behavior with a simple grid configuration I am hoping to track down.To start, here is my model:```public sealed class View{public View(Guid identity, DisplayName name, DateTimeOffset created){Identity = identity;Name = name;Created = created;}public Guid Identity { get; }public DisplayName Name { get; }public DateTimeOffset Created { get; }public void Deconstruct(out Guid identity, out DisplayName name, out DateTimeOffset created){identity = Identity;name = Name;created = Created;}}public sealed class DisplayName{public DisplayName(string provider, string name){Provider = provider;Name = name;}public string Provider { get; }public string Name { get; }public void Deconstruct(out string provider, out string name){provider = Provider;name = Name;}}public sealed class Entry{public bool Enabled { get; set; }public float Amount { get; set; } = .1f;public ICollectionViews { get; } = new List (); }```Here is my .razor file:```@{var view = content.To(); @($"{view.Created:f} UTC")}@code{[Parameter]public Entry Input { get; set; } = default!;}```When I add to the `Input.Views` collection and `StateHasChanged` the `SfGrid` does not update and refresh with the new state. However, if I change the SfGid to `DataSource="@Input.Views.ToList()"` the state changes as expected and the Input.Views is updated properly. However, this is unexpected and now I am binding to a copy of the view collection and not directly to the view collection itself. (Additionally, there is now another allocation to memory due to the new list.)Is there a property/concept here that I am overlooking? I would not expect to have to call `ToList` to update state properly and would prefer to bind directly to `Input.Views`.Thank you for any assistance you can provide!
Hi @Renjith,
Thank you for your reply and pardon my late reply here. I encountered this again with the SfListBox control and did some searching to see that I have already reported this here.
The problem is not during the `OnInitialized` event, but after a button click. Here is the code in its entirety to reproduce:
```
@page "/"
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Buttons
<SfGrid TValue="View" AllowPaging="false" AllowFiltering="false" AllowSorting="true" DataSource="@Views">
<GridPageSettings PageCount="10" />
<GridColumns>
<GridColumn Field="Name.Name" HeaderText="Name" />
<GridColumn Field="Name.Provider" HeaderText="Provider" />
<GridColumn Field="Created" HeaderText="Created" Type="ColumnType.DateTime" Width="250px">
@*<Template Context="content">
@{
var view = content.To<View>();
@($"{view.Created:f} UTC")
}
</Template>*@
</GridColumn>
</GridColumns>
</SfGrid>
<SfButton OnClick="OnClick">Click Me</SfButton>
@code{
protected override void OnInitialized()
{
}
public ICollection<View> Views { get; } = new List<View>();
public sealed class View
{
public View()
{
}
public View(Guid identity, DisplayName name, DateTimeOffset created)
{
Identity = identity;
Name = name;
Created = created;
}
public Guid Identity { get; set; }
public DisplayName Name { get; set; }
public DateTimeOffset Created { get; set; }
public void Deconstruct(out Guid identity, out DisplayName name, out DateTimeOffset created)
{
identity = Identity;
name = Name;
created = Created;
}
}
public sealed class DisplayName
{
public DisplayName()
{
}
public DisplayName(string provider, string name)
{
Provider = provider;
Name = name;
}
public string Provider { get; set; }
public string Name { get; set; }
public void Deconstruct(out string provider, out string name)
{
provider = Provider;
name = Name;
}
}
Task OnClick() {
Views.Add(new View() { Identity = new Guid(), Name = new DisplayName() { Provider = "Nancy", Name = "Fuller" }, Created = new DateTimeOffset() });
StateHasChanged();
return Task.CompletedTask;
}
}
```
Note that after clicking the `Click Me` button the grid does not update with the new collection, despite having called `StateHasChanged`.
Any further assistance would be appreciated.
Thank you,
Michael
Hi Michael,
We suggest you to call the Refresh() method of Grid to overcome the reported scenario. Please refer and use the code below,
<SfGrid @ref="GridRef" TValue="View"…> ... </SfGrid>
<SfButton OnClick="OnClick">Click Me</SfButton>
SfGrid<View> GridRef;
Task OnClick() { Views.Add(new View() { Identity = new Guid(), Name = new DisplayName() { Provider = "Nancy", Name = "Fuller" }, Created = new DateTimeOffset() }); StateHasChanged(); GridRef.Refresh(); return Task.CompletedTask; }
|
Please get back to us if you need further assistance.
Regards,
Renjith R
OK @Renjith thank you for the update. That was my understanding as well, but my expectation is that if I am binding on a collection that it would be refreshed without any intervention.
Note that the Refresh call is now asynchronous and can be done with the following with the latest version:
Task OnClick() {
Views.Add(new View() { Identity = new Guid(), Name = new DisplayName() { Provider = "Nancy", Name = "Fuller" }, Created = new DateTimeOffset() });
StateHasChanged();
return GridRef.Refresh();
}
Hi Mike-E,
When binding List/ICollection data to grid, then to update the dynamic changes in Grid it is a must to call the Refresh method. If you don’t want to call Refresh method, then you can bind data to Grid as ObservableCollection. Please refer the documentation and online sample demos showing CRUD operation with Observable Collection as data in Grid.
Documentation : https://blazor.syncfusion.com/documentation/datagrid/data-binding/#observable-collection
Online demo : https://blazor.syncfusion.com/demos/Grid/ObservableBinding?theme=bootstrap4
Please get back to us if you need further assistance.
Regards,
Renjith R
Ah! ObservableCollection! A blast from the past there, @Renjith. :) That makes a lot more sense now.
Thank you for the extra context/information.
Hi Mike-E,
Thanks for your update. Please get back to us if you need further assistance.
Regards,
Renjith R