Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Add IGridSort interface, fixes sorting when using ItemsProvider #3460

Merged
merged 10 commits into from
Mar 3, 2025
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
ο»Ώ<FluentDataGrid Items="@_gridData" ResizableColumns=true GridTemplateColumns="0.5fr 0.5fr">
<TemplateColumn Sortable="true" Title="First Name" SortBy="_firstNameSort">
@context.Properties["firstname"]
</TemplateColumn>

<TemplateColumn Sortable="true" Title="Last Name" SortBy="_lastNameSort">
@context.Properties["lastname"]
</TemplateColumn>
</FluentDataGrid>

@code {
private ColumnKeyGridSort<GridRow> _firstNameSort = new ColumnKeyGridSort<GridRow>(
"firstname",
(queryable, sortAscending) =>
{
if (sortAscending)
{
return queryable.OrderBy(x => x.Properties["firstname"]);
}
else
{
return queryable.OrderByDescending(x => x.Properties["firstname"]);
}
}
);

private ColumnKeyGridSort<GridRow> _lastNameSort = new ColumnKeyGridSort<GridRow>(
"lastname",
(queryable, sortAscending) =>
{
if (sortAscending)
{
return queryable.OrderBy(x => x.Properties["lastname"]);
}
else
{
return queryable.OrderByDescending(x => x.Properties["lastname"]);
}
}
);

private static readonly IQueryable<GridRow> _gridData = new GridRow[] {
new(new Dictionary<string, string>{ { "firstname", "Tom" }, { "lastname", "Cruise" } }),
new(new Dictionary<string, string>{ { "firstname", "Dolly" }, { "lastname", "Parton" } }),
new(new Dictionary<string, string>{ { "firstname", "Nicole" }, { "lastname", "Kidmon" } }),
new(new Dictionary<string, string>{ { "firstname", "James" }, { "lastname", "Bond" } }),
}.AsQueryable();

public record GridRow(Dictionary<string, string> Properties);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
</Description>
</DemoSection>

<DemoSection Title="Column Key Sort" Component="@typeof(DataGridColumnKeyGridSort)">
<Description>
<p>
In some instances, your dataset may not have a property on the class that can be used for sorting.
In this instance, you can supply a <code>ColumnKeyGridSort</code> that allows you to specify the name of your column and supply the logic for sorting.
</p>
</Description>
</DemoSection>

<h2>Documentation</h2>

Expand Down
2 changes: 1 addition & 1 deletion src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public abstract partial class ColumnBase<TGridItem>
/// <summary>
/// Gets or sets the sorting rules for a column.
/// </summary>
public abstract GridSort<TGridItem>? SortBy { get; set; }
public abstract IGridSort<TGridItem>? SortBy { get; set; }

/// <summary>
/// Gets or sets the initial sort direction.
Expand Down
42 changes: 42 additions & 0 deletions src/Core/Components/DataGrid/Columns/ColumnKeyGridSort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------
namespace Microsoft.FluentUI.AspNetCore.Components;

public class ColumnKeyGridSort<TGridItem> : IGridSort<TGridItem>
{
private readonly string _columnKey;
private readonly Func<IQueryable<TGridItem>, bool, IOrderedQueryable<TGridItem>>? _sortFunction;

public ColumnKeyGridSort(
string columnKey,
Func<IQueryable<TGridItem>, bool, IOrderedQueryable<TGridItem>>? sortFunction = null)
{
_columnKey = columnKey;
_sortFunction = sortFunction;
}

public IOrderedQueryable<TGridItem> Apply(IQueryable<TGridItem> queryable, bool ascending)
{
if (_sortFunction != null)
{
return _sortFunction(queryable, ascending);
}

// If no sort is provided, apply a sort that has no affect in order to be able to return an IOrderedQueryable
return queryable.OrderBy(x => 0);
}

public IReadOnlyCollection<SortedProperty> ToPropertyList(bool ascending)
{
return new List<SortedProperty> {
new SortedProperty
{
PropertyName = _columnKey,
Direction = ascending
? SortDirection.Ascending
: SortDirection.Descending,
}
};
}
}
6 changes: 3 additions & 3 deletions src/Core/Components/DataGrid/Columns/GridSort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Microsoft.FluentUI.AspNetCore.Components;
/// Represents a sort order specification used within <see cref="FluentDataGrid{TGridItem}"/>.
/// </summary>
/// <typeparam name="TGridItem">The type of data represented by each row in the grid.</typeparam>
public sealed class GridSort<TGridItem>
public sealed class GridSort<TGridItem> : IGridSort<TGridItem>
{
private const string ExpressionNotRepresentableMessage = "The supplied expression can't be represented as a property name for sorting. Only simple member expressions, such as @(x => x.SomeProperty), can be converted to property names.";

Expand Down Expand Up @@ -196,7 +196,7 @@ private GridSort<TGridItem> AddThenExpression(Func<IOrderedQueryable<TGridItem>,
return this;
}

internal IOrderedQueryable<TGridItem> Apply(IQueryable<TGridItem> queryable, bool ascending)
public IOrderedQueryable<TGridItem> Apply(IQueryable<TGridItem> queryable, bool ascending)
{
var orderedQueryable = _first(queryable, ascending);

Expand All @@ -211,7 +211,7 @@ internal IOrderedQueryable<TGridItem> Apply(IQueryable<TGridItem> queryable, boo
return orderedQueryable;
}

internal IReadOnlyCollection<SortedProperty> ToPropertyList(bool ascending)
public IReadOnlyCollection<SortedProperty> ToPropertyList(bool ascending)
{
if (ascending)
{
Expand Down
11 changes: 11 additions & 0 deletions src/Core/Components/DataGrid/Columns/IGridSort.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// ------------------------------------------------------------------------
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

namespace Microsoft.FluentUI.AspNetCore.Components;

public interface IGridSort<TGridItem>
{
IReadOnlyCollection<SortedProperty> ToPropertyList(bool ascending);
IOrderedQueryable<TGridItem> Apply(IQueryable<TGridItem> queryable, bool ascending);
}
10 changes: 5 additions & 5 deletions src/Core/Components/DataGrid/Columns/PropertyColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
// MIT License - Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------------------

using System.Linq.Expressions;
using System.Reflection;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure;
using Microsoft.FluentUI.AspNetCore.Components.Extensions;
using System.Linq.Expressions;
using System.Reflection;

namespace Microsoft.FluentUI.AspNetCore.Components;

Expand All @@ -22,8 +22,8 @@ public class PropertyColumn<TGridItem, TProp> : ColumnBase<TGridItem>, IBindable
private Expression<Func<TGridItem, TProp>>? _lastAssignedProperty;
private Func<TGridItem, string?>? _cellTextFunc;
private Func<TGridItem, string?>? _cellTooltipTextFunc;
private GridSort<TGridItem>? _sortBuilder;
private GridSort<TGridItem>? _customSortBy;
private IGridSort<TGridItem>? _sortBuilder;
private IGridSort<TGridItem>? _customSortBy;

public PropertyInfo? PropertyInfo { get; private set; }

Expand All @@ -47,7 +47,7 @@ public class PropertyColumn<TGridItem, TProp> : ColumnBase<TGridItem>, IBindable
[Parameter] public IComparer<TProp>? Comparer { get; set; } = null;

[Parameter]
public override GridSort<TGridItem>? SortBy
public override IGridSort<TGridItem>? SortBy
{
get => _customSortBy ?? _sortBuilder;
set => _customSortBy = value;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Components/DataGrid/Columns/SelectColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public DataGridSelectMode SelectMode

/// <inheritdoc />
[Parameter]
public override GridSort<TGridItem>? SortBy { get; set; }
public override IGridSort<TGridItem>? SortBy { get; set; }

/// <summary>
/// Allows to clear the selection.
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Components/DataGrid/Columns/TemplateColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class TemplateColumn<TGridItem> : ColumnBase<TGridItem>
[Parameter] public RenderFragment<TGridItem> ChildContent { get; set; } = EmptyChildContent;

/// <inheritdoc />
[Parameter] public override GridSort<TGridItem>? SortBy { get; set; }
[Parameter] public override IGridSort<TGridItem>? SortBy { get; set; }

/// <inheritdoc />
protected internal override void CellContent(RenderTreeBuilder builder, TGridItem item)
Expand Down
Loading