-
Notifications
You must be signed in to change notification settings - Fork 460
Closed
Labels
closed:doneWork is finishedWork is finished
Description
🐛 Bug Report
In a non-virtualized DataGrid with a SelectColumn and filtered items, every row click is triggering a data refresh.
💻 Repro or Code Sample
Taken from the DataGridTypical.razor sample - with an inserted SelectColumn.
@inject DataSource Data
<p>To test set ResizeType on the DataGrid to either DataGridResizeType.Discrete or DataGridResizeType.Exact</p>
<p>Remove the parameter completely to get the original behavior</p>
<div style="height: 380px; overflow-x:auto; display:flex;">
<FluentDataGrid @ref="grid"
Items="@FilteredItems"
ResizableColumns=true
ResizeType="DataGridResizeType.Discrete"
GridTemplateColumns="0.3fr 1fr 0.2fr 0.2fr 0.2fr 0.2fr"
Pagination="@pagination"
RowClass="@rowClass"
RowStyle="@rowStyle"
HeaderCellAsButtonWithMenu="true"
ColumnResizeLabels="@resizeLabels">
<SelectColumn TGridItem="@Country"
SelectMode="DataGridSelectMode.Single"
SelectFromEntireRow="true"
@bind-SelectedItems="@SelectedItems" />
<TemplateColumn Tooltip="true" TooltipText="@(c => "Flag of " + c.Name)" Title="Rank" SortBy="@rankSort" Align="Align.Center" InitialSortDirection="SortDirection.Ascending" IsDefaultSortColumn=true>
<img class="flag" src="_content/FluentUI.Demo.Shared/flags/@(context.Code).svg" alt="Flag of @(context.Code)" />
</TemplateColumn>
<PropertyColumn Property="@(c => c.Name)" Sortable="true" Filtered="!string.IsNullOrWhiteSpace(nameFilter)" Tooltip="true" Title="Name of the country">
<ColumnOptions>
<div class="search-box">
<FluentSearch Autofocus=true @bind-Value=nameFilter @oninput="HandleCountryFilter" @onkeydown="HandleCloseFilterAsync" @bind-Value:after="HandleClear" Placeholder="Country name..." Style="width: 100%;" Label="Filter" />
</div>
</ColumnOptions>
</PropertyColumn>
<PropertyColumn Property="@(c => c.Medals.Gold)" Sortable="true" Align="Align.Start" Tooltip="true" TooltipText="@(c => "That is " + c.Medals.Gold + " x GOLD!!")" />
<PropertyColumn Property="@(c => c.Medals.Silver)" Sortable="true" Align="Align.Center" Tooltip="true" />
<PropertyColumn Property="@(c => c.Medals.Bronze)" Sortable="false" Align="Align.End" />
<PropertyColumn Property="@(c => c.Medals.Total)" Sortable="true" Filtered="@(minMedals != 0 || maxMedals != 130)" Align="Align.End" Tooltip="true">
<ColumnOptions>
<div style="width: 100%; height: 150px;">
<FluentSlider Label="@($"Min ({minMedals})")" Min="0" Max="150" Step="1" Orientation="Orientation.Horizontal" @bind-Value=minMedals Immediate="true" Style="width: 100%;">
<FluentSliderLabel Position="0">0</FluentSliderLabel>
<FluentSliderLabel Position="50">50</FluentSliderLabel>
<FluentSliderLabel Position="100">100</FluentSliderLabel>
<FluentSliderLabel Position="150">150</FluentSliderLabel>
</FluentSlider>
<br /><br />
<FluentSlider Label="@($"Max ({maxMedals})")" Min="0" Max="150" Step="1" Orientation="Orientation.Horizontal" @bind-Value=maxMedals Immediate="true" Style="width: 100%;">
<FluentSliderLabel Position="0">0</FluentSliderLabel>
<FluentSliderLabel Position="50">50</FluentSliderLabel>
<FluentSliderLabel Position="100">100</FluentSliderLabel>
<FluentSliderLabel Position="150">150</FluentSliderLabel>
</FluentSlider>
</div>
</ColumnOptions>
</PropertyColumn>
</FluentDataGrid>
</div>
<FluentPaginator State="@pagination" />
<FluentSwitch @bind-Value="@_clearItems"
@bind-Value:after="ToggleItemsAsync"
UncheckedMessage="Clear all results"
CheckedMessage="Restore all results">
</FluentSwitch>
@code {
FluentDataGrid<Country>? grid;
bool _clearItems = false;
IQueryable<Country>? items;
PaginationState pagination = new PaginationState { ItemsPerPage = 10 };
string nameFilter = string.Empty;
int minMedals;
int maxMedals = 130;
IEnumerable<Country> SelectedItems = [];
ColumnResizeLabels resizeLabels = ColumnResizeLabels.Default with
{
DiscreteLabel = "Width (+/- 10px)",
ResetAriaLabel = "Restore"
};
GridSort<Country> rankSort = GridSort<Country>
.ByDescending(x => x.Medals.Gold)
.ThenDescending(x => x.Medals.Silver)
.ThenDescending(x => x.Medals.Bronze);
Func<Country, string?> rowClass = x => x.Name.StartsWith("A") ? "highlighted" : null;
Func<Country, string?> rowStyle = x => x.Name.StartsWith("Au") ? "background-color: var(--highlight-bg)" : null;
//IQueryable<Country>? FilteredItems => items?.Where(x => x.Name.Contains(nameFilter, StringComparison.CurrentCultureIgnoreCase));
IQueryable<Country>? FilteredItems
{
get
{
var result = items?.Where(c => c.Medals.Total <= maxMedals);
if (result is not null && !string.IsNullOrEmpty(nameFilter))
{
result = result.Where(c => c.Name.Contains(nameFilter, StringComparison.CurrentCultureIgnoreCase));
}
if (result is not null && minMedals > 0)
{
result = result.Where(c => c.Medals.Total >= minMedals);
}
return result;
}
}
protected override async Task OnInitializedAsync()
{
items = (await Data.GetCountriesAsync()).AsQueryable();
}
private void HandleCountryFilter(ChangeEventArgs args)
{
if (args.Value is string value)
{
nameFilter = value;
}
}
private void HandleClear()
{
if (string.IsNullOrWhiteSpace(nameFilter))
{
nameFilter = string.Empty;
}
}
private async Task HandleCloseFilterAsync(KeyboardEventArgs args)
{
if (args.Key == "Escape")
{
nameFilter = string.Empty;
}
if (args.Key == "Enter" && grid is not null)
{
await grid.CloseColumnOptionsAsync();
}
}
private async Task ToggleItemsAsync()
{
if (_clearItems)
{
items = null;
}
else
{
items = (await Data.GetCountriesAsync()).AsQueryable();
}
}
}
🤔 Expected Behavior
I wouldn't expect any data refreshes just for selecting a row.
😯 Current Behavior
Every Select/Deselect is now triggering a data refresh.
If I ignore the filters and change the Items attribute of the FluentDataGrid of the sample to items instead of FilteredItems then the behavior is as expected (with no unnecessary data refreshes in case of a real Queryable items object).
🌍 Your Environment
- .NET 9.0
- FluentUI version 4.11.9
Metadata
Metadata
Assignees
Labels
closed:doneWork is finishedWork is finished