Repository: MudBlazor/MudBlazor (2026-04-02T10:45:57Z)

Issue:
MudDataGrid needs a SortChanged event that can be subscribed to.
### Feature request type

Enhance component

### Component name

MudDataGrid

### Is your feature request related to a problem?

No

### Describe the solution you'd like

Currently, there is no way to easily tell when the sort has changed in the data grid. There is a SortDefinitions parameter but the type is an Dictionary<string, SortDefinition> which does not allow notifying when a definition has been added, removed or changed. There needs to be an event, SortChanged than can be subscribed to for notifying when the sort of the data grid has changed.

### Have you seen this feature anywhere else?

No

### Describe alternatives you've considered

The only solution really is implementing your own ObservableDictionary.

### Pull Request

- [ ] I would like to do a Pull Request

### Code of Conduct

- [X] I agree to follow this project's Code of Conduct


Discussion:
Seconded!
Hi, will this event be available in the next future?
I see SortChangedEvent in the Documentation API but this event is not public
thank you
> Hi, will this event be available in the next future?

Pull Request is welcome.
> > Hi, will this event be available in the next future?
> 
> Pull Request is welcome.

sorry, what do you mean?
> sorry, what do you mean?

MudBlazor is a community project. When someone needs a feature, users like you can implement it, post the code through a pull request, and then the team will review it. If everything is okay, the code will be added to the MudBlazor codebase.
> MudBlazor is a community project. When someone needs a feature, users like you can implement it, post the code through a pull request, and then the team will review it. If everything is okay, the code will be added to the MudBlazor codebase.

it's ok, but, as the documentation says that there is such an event, I think that this is a bug either in the code or in the docs.

> it's ok, but, as the documentation says that there is such an event, I think that this is a bug either in the code or in the docs.

It's bug in the docs, it's not suppose to show internal api, currently the API docs going through a rewrite, so yeah there are some bugs and missing features in the docs.
Any plans to expose a grid State property (at least filters, sorts) for manually assembling a query when a search button is clicked, and retrieving items then assigning to the Items property instead of using ServerData?



Patch:
diff --git a/src/MudBlazor/Components/DataGrid/MudDataGrid.razor.cs b/src/MudBlazor/Components/DataGrid/MudDataGrid.razor.cs
index 45d7e1d7c056..75c74c28b662 100644
--- a/src/MudBlazor/Components/DataGrid/MudDataGrid.razor.cs
+++ b/src/MudBlazor/Components/DataGrid/MudDataGrid.razor.cs
@@ -282,6 +282,17 @@ private Task ItemUpdatedAsync(MudItemDropInfo<Column<T>> dropItem)
 
         #region EventCallbacks
 
+        /// <summary>
+        /// Occurs when the <see cref="SortDefinitions"/> have changed.
+        /// </summary>
+        /// <remarks>
+        /// This callback is raised when the grid's sort state is updated.
+        /// When <see cref="ServerData"/> or <see cref="VirtualizeServerData"/> is used,
+        /// it is invoked before the data reload triggered by the new sort completes.
+        /// </remarks>        
+        [Parameter]
+        public EventCallback<Dictionary<string, SortDefinition<T>>> SortChanged { get; set; }
+
         /// <summary>
         /// Occurs when the <see cref="SelectedItem"/> has changed.
         /// </summary>
@@ -2286,6 +2297,10 @@ private async Task ClearCurrentSortings()
         private async Task InvokeSortUpdates(Dictionary<string, SortDefinition<T>> activeSortDefinitions, HashSet<string>? removedSortDefinitions)
         {
             SortChangedEvent?.Invoke(activeSortDefinitions, removedSortDefinitions);
+            if (_isFirstRendered)
+            {
+                await SortChanged.InvokeAsync(new Dictionary<string, SortDefinition<T>>(activeSortDefinitions));
+            }
 
             if (_isFirstRendered)
             {


Test patch:
diff --git a/src/MudBlazor.UnitTests.Viewer/TestComponents/DataGrid/DataGridEventCallbacksTest.razor b/src/MudBlazor.UnitTests.Viewer/TestComponents/DataGrid/DataGridEventCallbacksTest.razor
index d09780c9d6fa..beb433886465 100644
--- a/src/MudBlazor.UnitTests.Viewer/TestComponents/DataGrid/DataGridEventCallbacksTest.razor
+++ b/src/MudBlazor.UnitTests.Viewer/TestComponents/DataGrid/DataGridEventCallbacksTest.razor
@@ -3,6 +3,7 @@
 <MudDataGrid T="Item" Items="@_items" EditMode="@DataGridEditMode.Cell"
              RowClick="@OnRowClick"
              RowContextMenuClick="@OnRowContextMenuClick"
+             SortChanged="@OnSortChanged"
              SelectedItemChanged="@OnSelectedItemChanged"
              SelectedItemsChanged="@OnSelectedItemsChanged"
              FilterChanged="@OnFilterChanged"
@@ -27,6 +28,7 @@
 
     public bool RowClicked { get; set; }
     public bool RowContextMenuClicked { get; set; }
+    public bool SortChanged { get; set; }
     public bool SelectedItemChanged { get; set; }
     public bool SelectedItemsChanged { get; set; }
     public bool FilterChanged { get; set; }
@@ -45,6 +47,11 @@
         RowContextMenuClicked = true;
     }
 
+    private void OnSortChanged(Dictionary<string, SortDefinition<Item>> sorts)
+    {
+        SortChanged = true;
+    }
+
     private void OnSelectedItemChanged(Item item)
     {
         SelectedItemChanged = true;
diff --git a/src/MudBlazor.UnitTests/Components/DataGridTests.cs b/src/MudBlazor.UnitTests/Components/DataGridTests.cs
index 78412f20f3a4..d808ea25cb5a 100644
--- a/src/MudBlazor.UnitTests/Components/DataGridTests.cs
+++ b/src/MudBlazor.UnitTests/Components/DataGridTests.cs
@@ -1293,6 +1293,7 @@ public async Task DataGridEventCallbacks()
             // Include callbacks in test coverage.
             dataGrid.Instance.RowClick.HasDelegate.Should().Be(true);
             dataGrid.Instance.RowContextMenuClick.HasDelegate.Should().Be(true);
+            dataGrid.Instance.SortChanged.HasDelegate.Should().Be(true);
             dataGrid.Instance.SelectedItemChanged.HasDelegate.Should().Be(true);
             dataGrid.Instance.FilterChanged.HasDelegate.Should().Be(true);
             dataGrid.Instance.CommittedItemChanges.Should().NotBeNull();
@@ -1319,12 +1320,15 @@ await dataGrid.SetParametersAndRenderAsync(parameters => parameters
             // Make sure that the callbacks have not been fired yet.
             comp.Instance.RowClicked.Should().Be(false);
             comp.Instance.RowContextMenuClicked.Should().Be(false);
+            comp.Instance.SortChanged.Should().Be(false);
             comp.Instance.SelectedItemChanged.Should().Be(false);
             comp.Instance.FilterChanged.Should().Be(false);
             comp.Instance.CommittedItemChanges.Should().Be(false);
             comp.Instance.StartedEditingItem.Should().Be(false);
             comp.Instance.CanceledEditingItem.Should().Be(false);
 
+            await dataGrid.InvokeAsync(() => dataGrid.Instance.SetSortAsync(nameof(DataGridEventCallbacksTest.Item.Name), SortDirection.Ascending, x => x.Name));
+
             // Fire RowClick, SelectedItemChanged, SelectedItemsChanged, and StartedEditingItem callbacks.
             await dataGrid.FindAll(".mud-table-body tr")[0].ClickAsync();
 
@@ -1337,6 +1341,7 @@ await dataGrid.SetParametersAndRenderAsync(parameters => parameters
             // Make sure that the callbacks have been fired.
             comp.Instance.RowClicked.Should().Be(true);
             comp.Instance.RowContextMenuClicked.Should().Be(true);
+            comp.Instance.SortChanged.Should().Be(true);
             comp.Instance.SelectedItemChanged.Should().Be(true);
             comp.Instance.FilterChanged.Should().Be(false);
             comp.Instance.CommittedItemChanges.Should().Be(true);