diff --git a/WHATSNEW.md b/WHATSNEW.md
index 5eaefd1e1a..af778cb7e3 100644
--- a/WHATSNEW.md
+++ b/WHATSNEW.md
@@ -1,3 +1,8 @@
+## v4.6.2
+
+### Components
+[DataGrid] Add remove sort capability on columns ([#1826](https://github.com/microsoft/fluentui-blazor/pull/1826))
+
## V4.6.1
### Demo site and documentation
diff --git a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
index 9fd2a1e2e9..a774d3169c 100644
--- a/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
+++ b/examples/Demo/Shared/Microsoft.FluentUI.AspNetCore.Components.xml
@@ -1084,20 +1084,20 @@
- Gets or sets the title text for the column.
+ Gets or sets the title text for the column.
This is rendered automatically if is not used.
- Gets or sets the an optional CSS class name.
+ Gets or sets the an optional CSS class name.
If specified, this is included in the class attribute of header and grid cells
for this column.
- Gets or sets an optional CSS style specification.
+ Gets or sets an optional CSS style specification.
If specified, this is included in the style attribute of header and grid cells
for this column.
@@ -1119,7 +1119,7 @@
- Gets or sets an optional template for this column's header cell.
+ Gets or sets an optional template for this column's header cell.
If not specified, the default header template includes the along with any applicable sort indicators and options buttons.
@@ -1471,6 +1471,13 @@
The direction of sorting. If the value is , then it will toggle the direction on each call.
A representing the completion of the operation.
+
+
+ Removes the grid's sort on double click if this is specified currently sorted on.
+
+ The column to check against the current sorted on column.
+ A representing the completion of the operation.
+
Displays the UI for the specified column, closing any other column
diff --git a/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor b/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor
index 64df043ce0..5e285a1804 100644
--- a/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor
+++ b/examples/Demo/Shared/Pages/DataGrid/DataGridPage.razor
@@ -21,6 +21,18 @@
as this will interfere with the DataGrid scripts that use this attribute as well. Use the RowClass
instead.
+Accessibility
+
+ You can use the Arrow keys to navigate through a DataGrid. When a header cell is focused and the column is sortable, you can use the Tab key to select the sort button.
+ Pressing the Enter key will toggle the sorting direction. Pressing Ctrl+Enter removes the column sorting and restores the default/start situation with regards to sorting.
+ You cannot not remove the default grid sorting with this key combination.
+
+
+ When a header cell is focused and the column allows setting options, you can use the Tab key to select the options button.
+ Pressing the Enter key then will toggle the options popover. Pressing Esc closes the popover
+ .
+
+
Examples
diff --git a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor
index 2127311907..164d8bcea1 100644
--- a/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor
+++ b/examples/Demo/Shared/Pages/DataGrid/Examples/DataGridTypical.razor
@@ -8,7 +8,7 @@
-
+
@@ -21,8 +21,8 @@
-
@@ -37,7 +37,7 @@
.ByDescending(x => x.Medals.Gold)
.ThenDescending(x => x.Medals.Silver)
.ThenDescending(x => x.Medals.Bronze);
-
+
Func rowClass = x => x.Name.StartsWith("A") ? "highlighted-row" : null;
Func rowStyle = x => x.Name.StartsWith("Au") ? "background-color: var(--highlight-bg);" : null;
diff --git a/examples/Demo/Shared/wwwroot/docs/WhatsNew.md b/examples/Demo/Shared/wwwroot/docs/WhatsNew.md
index c159023a7b..c421dcf1e8 100644
--- a/examples/Demo/Shared/wwwroot/docs/WhatsNew.md
+++ b/examples/Demo/Shared/wwwroot/docs/WhatsNew.md
@@ -1,3 +1,8 @@
+## v4.6.2
+
+### Components
+[DataGrid] Add remove sort capability on columns ([#1826](https://github.com/microsoft/fluentui-blazor/pull/1826))
+
## V4.6.1
### Demo site and documentation
@@ -8,7 +13,6 @@
- [Demo & docs] CSS files improvements ([#1807](https://github.com/microsoft/fluentui-blazor/pull/1807))
- [Demo & docs] The empty CSS rule in site.css has been removed ([#1809](https://github.com/microsoft/fluentui-blazor/pull/1809))
-
### Components
- [AppBar] Add Count parameter and facilitate OnClick without navigation ([#1790](https://github.com/microsoft/fluentui-blazor/pull/1790))
- [CounterBadge] Add ShowWhen, Dot, and VerticalPosition ([#1786](https://github.com/microsoft/fluentui-blazor/pull/1786))
diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor b/src/Core/Components/DataGrid/Columns/ColumnBase.razor
index a3fc18e1e7..b273076a44 100644
--- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor
+++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor
@@ -1,4 +1,4 @@
-@using Microsoft.AspNetCore.Components.Rendering
+@using Microsoft.AspNetCore.Components.Rendering
@using Microsoft.FluentUI.AspNetCore.Components.DataGrid.Infrastructure
@namespace Microsoft.FluentUI.AspNetCore.Components
@typeparam TGridItem
@@ -20,7 +20,7 @@
@if (ColumnOptions is not null && (Align == Align.Start || Align == Align.Center))
{
Grid.ShowColumnOptionsAsync(this))" aria-label="Filter this column">
- @if(Filtered.GetValueOrDefault())
+ @if (Filtered.GetValueOrDefault())
{
}
@@ -33,22 +33,26 @@
if (Sortable.HasValue ? Sortable.Value : IsSortableByDefault())
{
- Grid.SortByColumnAsync(this))" aria-label="@tooltip" title="@tooltip">
- @Title
+
+ Grid.RemoveSortByColumnAsync(this))" @oncontextmenu:preventDefault>
+ Grid.SortByColumnAsync(this))" aria-label="@tooltip" title="@tooltip">
+ @Title
- @if (Grid.SortByAscending.HasValue && ShowSortIcon)
- {
- if (Grid.SortByAscending == true)
+ @if (Grid.SortByAscending.HasValue && ShowSortIcon)
{
-
+ if (Grid.SortByAscending == true)
+ {
+
+ }
+ else
+ {
+
+ }
}
- else
- {
-
- }
- }
-
+
+
+
}
else
{
@@ -60,7 +64,7 @@
@if (ColumnOptions is not null && Align == Align.End)
{
Grid.ShowColumnOptionsAsync(this))" aria-label="Filter this column">
- @if(Filtered.GetValueOrDefault())
+ @if (Filtered.GetValueOrDefault())
{
}
diff --git a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs
index 86bb5677ca..cbd6eb6702 100644
--- a/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs
+++ b/src/Core/Components/DataGrid/Columns/ColumnBase.razor.cs
@@ -14,20 +14,20 @@ public abstract partial class ColumnBase
[CascadingParameter] internal InternalGridContext InternalGridContext { get; set; } = default!;
///
- /// Gets or sets the title text for the column.
+ /// Gets or sets the title text for the column.
/// This is rendered automatically if is not used.
///
[Parameter] public string? Title { get; set; }
///
- /// Gets or sets the an optional CSS class name.
+ /// Gets or sets the an optional CSS class name.
/// If specified, this is included in the class attribute of header and grid cells
/// for this column.
///
[Parameter] public string? Class { get; set; }
///
- /// Gets or sets an optional CSS style specification.
+ /// Gets or sets an optional CSS style specification.
/// If specified, this is included in the style attribute of header and grid cells
/// for this column.
///
@@ -49,7 +49,7 @@ public abstract partial class ColumnBase
[Parameter] public Func? TooltipText { get; set; }
///
- /// Gets or sets an optional template for this column's header cell.
+ /// Gets or sets an optional template for this column's header cell.
/// If not specified, the default header template includes the along with any applicable sort indicators and options buttons.
///
[Parameter] public RenderFragment>? HeaderCellItemTemplate { get; set; }
@@ -135,6 +135,14 @@ public abstract partial class ColumnBase
/// True if the column should be sortable by default, otherwise false.
protected virtual bool IsSortableByDefault() => false;
+ protected void HandleKeyDown(FluentKeyCodeEventArgs e)
+ {
+ if (e.CtrlKey && e.Key == KeyCode.Enter)
+ {
+ Grid.RemoveSortByColumnAsync(this);
+ }
+ }
+
public bool ShowSortIcon;
///
diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs
index ba9689cba7..d3b481115f 100644
--- a/src/Core/Components/DataGrid/FluentDataGrid.razor.cs
+++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.cs
@@ -277,6 +277,7 @@ internal void AddColumn(ColumnBase column, SortDirection? initialSort
{
_sortByColumn = column;
_sortByAscending = initialSortDirection.Value != SortDirection.Descending;
+ _internalGridContext.DefaultSortColumn = (column, initialSortDirection.Value);
}
}
}
@@ -319,6 +320,23 @@ public Task SortByColumnAsync(ColumnBase column, SortDirection direct
return RefreshDataAsync();
}
+ ///
+ /// Removes the grid's sort on double click if this is specified currently sorted on.
+ ///
+ /// The column to check against the current sorted on column.
+ /// A representing the completion of the operation.
+ public Task RemoveSortByColumnAsync(ColumnBase column)
+ {
+ if (_sortByColumn == column && !column.IsDefaultSortColumn)
+ {
+ _sortByColumn = _internalGridContext.DefaultSortColumn.Column ?? null;
+ _sortByAscending = _internalGridContext.DefaultSortColumn.Direction != SortDirection.Descending;
+ }
+
+ StateHasChanged(); // We want to see the updated sort order in the header, even before the data query is completed
+ return RefreshDataCoreAsync();
+ }
+
///
/// Displays the UI for the specified column, closing any other column
/// options UI that was previously displayed.
@@ -331,6 +349,10 @@ public Task ShowColumnOptionsAsync(ColumnBase column)
StateHasChanged();
return Task.CompletedTask;
}
+ public void SetLoadingState(bool loading)
+ {
+ Loading = loading;
+ }
///
/// Instructs the grid to re-fetch and render the current data from the supplied data source
@@ -342,11 +364,6 @@ public async Task RefreshDataAsync()
await RefreshDataCoreAsync();
}
- public void SetLoadingState(bool loading)
- {
- Loading = loading;
- }
-
// Same as RefreshDataAsync, except without forcing a re-render. We use this from OnParametersSetAsync
// because in that case there's going to be a re-render anyway.
private async Task RefreshDataCoreAsync()
diff --git a/src/Core/Components/DataGrid/FluentDataGrid.razor.js b/src/Core/Components/DataGrid/FluentDataGrid.razor.js
index d005da7c8b..96e06a8a8b 100644
--- a/src/Core/Components/DataGrid/FluentDataGrid.razor.js
+++ b/src/Core/Components/DataGrid/FluentDataGrid.razor.js
@@ -16,6 +16,7 @@ export function init(gridElement) {
if (columnOptionsElement) {
if (event.key === "Escape") {
gridElement.dispatchEvent(new CustomEvent('closecolumnoptions', { bubbles: true }));
+ gridElement.focus();
}
columnOptionsElement.addEventListener(
"keydown",
diff --git a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css
index bc391f64bf..0610a58026 100644
--- a/src/Core/Components/DataGrid/FluentDataGridCell.razor.css
+++ b/src/Core/Components/DataGrid/FluentDataGridCell.razor.css
@@ -1,4 +1,4 @@
-fluent-data-grid-cell {
+fluent-data-grid-cell {
text-overflow: ellipsis;
}
@@ -10,28 +10,44 @@
.column-header {
display: flex;
+ width: 100%;
+ height: 100%;
align-self: center;
padding-inline: 0;
+ padding-right: 1px;
+ padding-left: 1px;
}
.column-header.col-justify-end, .column-header.col-justify-right {
- width: 100%;
- padding: 0;
+
+ padding-right: 1px;
+ padding-left: 1px;
justify-content: end;
}
.column-header.col-justify-center {
- width: 100%;
- padding: 0;
+
+ padding-left: 1px;
+ padding-right: 1px;
justify-content: center;
}
- .column-header > ::deep .col-sort-button {
+ .column-header > ::deep .keycapture {
+ display: flex;
+ flex-grow: 1;
+ }
+
+ .column-header > ::deep .keycapture .col-sort-container {
+ display: flex;
+ flex-grow: 1;
+ }
+
+ .column-header > ::deep .keycapture .col-sort-container .col-sort-button {
flex-grow: 1;
padding-inline-end: 5px;
}
- .column-header > ::deep .col-sort-button::part(content) {
+ .column-header > ::deep .keycapture .col-sort-container .col-sort-button::part(content) {
overflow: hidden;
text-overflow: ellipsis;
}
diff --git a/src/Core/Components/DataGrid/Infrastructure/InternalGridContext.cs b/src/Core/Components/DataGrid/Infrastructure/InternalGridContext.cs
index bd5ee22a8b..3ca3080996 100644
--- a/src/Core/Components/DataGrid/Infrastructure/InternalGridContext.cs
+++ b/src/Core/Components/DataGrid/Infrastructure/InternalGridContext.cs
@@ -10,6 +10,9 @@ internal sealed class InternalGridContext
private int _rowId = 0;
private int _cellId = 0;
+ public (ColumnBase? Column, SortDirection? Direction) DefaultSortColumn { get; set; }
+ //public SortDirection? DefaultSortDirection { get; set; }
+
public Dictionary> Rows { get; set; } = [];
public FluentDataGrid Grid { get; }
diff --git a/src/Core/Components/Dialog/Services/DialogService-Dialog.cs b/src/Core/Components/Dialog/Services/DialogService-Dialog.cs
index 373849691e..d8d6682f0f 100644
--- a/src/Core/Components/Dialog/Services/DialogService-Dialog.cs
+++ b/src/Core/Components/Dialog/Services/DialogService-Dialog.cs
@@ -72,7 +72,7 @@ public async Task ShowDialogAsync(RenderFragment renderFragmen
return await ShowDialogAsync(typeof(RenderFragmentDialog), renderFragment, dialogParameters);
}
- private DialogParameters FixPanelParameters(DialogParameters value)
+ private static DialogParameters FixPanelParameters(DialogParameters value)
{
value.DialogType = DialogType.Panel;