I'm having a problem that I can't get my head around. I've read numerous articles online and nobody appears to have come across any solution which works for me.
Goal
I want to display a file selector, upon selecting a file it should show the selected files within a RadzenDataGrid
.
The Problem
After selecting the files the User Interface isn't updated. I can't quite tell whether Radzen, Blazor (or I) am at fault, but I can confirm that the fileGrid.Data
property is indeed being updated.
I should also point out I have tried implementing StateHasChanged()
to no avail. It appears fileGrid.Reload()
calls this anyway. Further to this I've also tried InvokeAsync(StateHasChanged())
with no luck either.
Any help would be appreciated.
Here's the .razor
page at hand.
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0" />
</head>
<div>
<InputFile id="fileInput" class="hidden" accept="@Accept" OnChange="HandleFileChange" multiple />
<RadzenText TextStyle="TextStyle.Overline">@Text</RadzenText>
<label for="fileInput">
<span class="btn material-symbols-outlined">
Add
</span>
</label>
<RadzenDataGrid @ref="fileGrid" Data=files PageSize="10">
<Columns>
<RadzenDataGrid TItem="IBrowserFile" Property="Name" Title="Name" />
<RadzenDataGrid TItem="IBrowserFile" Property="Size" Title="Size" />
<RadzenDataGrid TItem="IBrowserFile">
<Template Context="item">
<RadzenIcon class="action-icon float-right" Icon="delete_forever" @onclick="@(() => RemoveFile(item))" />
</Template>
</RadzenDataGrid>
</Columns>
</RadzenDataGrid>
</div>
<Toast @ref="toast" />
<style>
.hidden {
display: none;
}
.btn {
cursor: pointer;
padding: 0;
margin: 0;
}
</style>
@code {
[Parameter]
public string Accept { get; set; } = "*";
[Parameter]
public string Text { get; set; } = "Files";
[Parameter]
public EventCallback<List<IBrowserFile>> FilesChanged { get; set; }
List<IBrowserFile> files { get; set; } = new();
Toast toast;
RadzenDataGrid<IBrowserFile> fileGrid;
const int maxFileSizeMb = 10;
private async Task HandleFileChange(InputFileChangeEventArgs eventArgs)
{
List<IBrowserFile> validFiles = new();
foreach (var file in eventArgs.GetMultipleFiles())
{
if (ValidateSize(file))
validFiles.Add(file);
else
toast.Show($"{file.Name} exceeds the file limit of {maxFileSizeMb}mb");
}
files = validFiles;
// Notify the UI to update
if (fileGrid != null)
{
await fileGrid.Reload();
}
}
private bool ValidateSize(IBrowserFile file) => file.Size < maxFileSizeMb * 1024 * 1024;
private void RemoveFile(IBrowserFile file)
{
files.Remove(file);
// Reload the data grid
fileGrid?.Reload();
}
}
You are using the wrong element to display data in grid. Change RadzenDataGrid
to RadzenDataGridColumn
.
<RadzenDataGrid @ref="fileGrid" Data=files PageSize="10">
<Columns>
@* Here is the modification *@
<RadzenDataGridColumn TItem="IBrowserFile" Property="Name" Title="Name" />
<RadzenDataGridColumn TItem="IBrowserFile" Property="Size" Title="Size" />
<RadzenDataGridColumn TItem="IBrowserFile">
<Template Context="item">
<span class="material-icons action-icon" @onclick="@(() => RemoveFile(item))">
delete_forever
</span>
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
Also you seem to only display the newly added file for testing, just in case, you can modify the file list to show all files.
//files = validFiles;
//Previous code gets only the new added file. Code below gets all the lists
files.AddRange(validFiles);