Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1842,6 +1842,9 @@
<member name="M:Microsoft.FluentUI.AspNetCore.Components.SelectColumn`1.OnKeyAllAsync(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs)">
<summary />
</member>
<member name="M:Microsoft.FluentUI.AspNetCore.Components.SelectColumn`1.Dispose">
<inheritdoc />
</member>
<member name="T:Microsoft.FluentUI.AspNetCore.Components.SortedProperty">
<summary>
Holds the name of a property and the direction to sort by.
Expand Down
35 changes: 34 additions & 1 deletion src/Core/Components/DataGrid/Columns/SelectColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.FluentUI.AspNetCore.Components.Infrastructure;

namespace Microsoft.FluentUI.AspNetCore.Components;

/// <summary>
/// Represents a <see cref="FluentDataGrid{TGridItem}"/> column whose cells render a selected checkbox updated when the user click on a row.
/// </summary>
/// <typeparam name="TGridItem">The type of data represented by each row in the grid.</typeparam>
public class SelectColumn<TGridItem> : ColumnBase<TGridItem>
public class SelectColumn<TGridItem> : ColumnBase<TGridItem>, IDisposable
{
/// <summary>
/// List of keys to press, to select/unselect a row.
Expand All @@ -27,13 +28,23 @@ public class SelectColumn<TGridItem> : ColumnBase<TGridItem>
private DataGridSelectMode _selectMode = DataGridSelectMode.Single;
private readonly List<TGridItem> _selectedItems = [];

private readonly EventCallbackSubscriber<object?> _itemsChanged;

/// <summary>
/// Initializes a new instance of <see cref="SelectColumn{TGridItem}"/>.
/// </summary>
public SelectColumn()
{
Width = "50px";
ChildContent = GetDefaultChildContent();

_itemsChanged = new(EventCallback.Factory.Create<object?>(this, UpdateSelectedItemsAsync));
}

protected override void OnInitialized()
{
_itemsChanged.SubscribeOrMove(InternalGridContext.ItemsChanged);
base.OnInitialized();
}

/// <summary>
Expand Down Expand Up @@ -326,6 +337,21 @@ Task CallOnSelectAsync(TGridItem item, bool isSelected)
}
}

private async Task UpdateSelectedItemsAsync()
{

if (!SelectedItems.Any() || InternalGridContext == null || InternalGridContext.Items == null)
{
return;
}

var itemsToRemove = _selectedItems.Where(item => !InternalGridContext.Items.Contains(item)).ToList();
foreach (var item in itemsToRemove)
{
await AddOrRemoveSelectedItemAsync(item);
}
}

private Icon GetIcon(bool? selected)
{
if (selected == true)
Expand Down Expand Up @@ -555,6 +581,13 @@ internal async Task OnKeyAllAsync(KeyboardEventArgs e)
await OnClickAllAsync(new MouseEventArgs());
}
}

/// <inheritdoc />
public void Dispose()
{
_itemsChanged.Dispose();

}
}

public record SelectAllTemplateArgs(bool? AllSelected) { }
4 changes: 3 additions & 1 deletion src/Core/Components/DataGrid/FluentDataGrid.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,8 @@ private async Task RefreshDataCoreAsync()
if (!thisLoadCts.IsCancellationRequested)
{
_internalGridContext.Items = result.Items;
await _internalGridContext.ItemsChanged.InvokeCallbacksAsync(null);

_internalGridContext.TotalItemCount = result.TotalItemCount;
if (RefreshItems is null)
{
Expand Down Expand Up @@ -831,7 +833,7 @@ private async Task RefreshDataCoreAsync()

if (!request.CancellationToken.IsCancellationRequested)
{
// ARIA's rowcount is part of the UI, so it should reflect what the human user regards as the number of rows in the table,
// ARIA's row count is part of the UI, so it should reflect what the human user regards as the number of rows in the table,
// not the number of physical <tr> elements. For virtualization this means what's in the entire scrollable range, not just
// the current viewport. In the case where you're also paginating then it means what's conceptually on the current page.
// TODO: This currently assumes we always want to expand the last page to have ItemsPerPage rows, but the experience might
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// ------------------------------------------------------------------------
// This file is licensed to you under the MIT License.
// ------------------------------------------------------------------------

using Microsoft.FluentUI.AspNetCore.Components.Infrastructure;

namespace Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure;

// The grid cascades this so that descendant columns can talk back to it. It's an internal type
// so that it doesn't show up by mistake in unrelated components.
internal sealed class InternalGridContext<TGridItem>
internal sealed class InternalGridContext<TGridItem>(FluentDataGrid<TGridItem> grid)
{
private int _index = 0;
private int _rowId = 0;
Expand All @@ -19,13 +23,9 @@ internal sealed class InternalGridContext<TGridItem>
public int TotalItemCount { get; set; }
public int TotalViewItemCount { get; set; }

public FluentDataGrid<TGridItem> Grid { get; }
public FluentDataGrid<TGridItem> Grid { get; } = grid;
public EventCallbackSubscribable<object?> ColumnsFirstCollected { get; } = new();

public InternalGridContext(FluentDataGrid<TGridItem> grid)
{
Grid = grid;
}
public EventCallbackSubscribable<object?> ItemsChanged { get; } = new();

public int GetNextRowId()
{
Expand Down
Loading