diff --git a/demo/Semi.Avalonia.Demo.Desktop/App.axaml b/demo/Semi.Avalonia.Demo.Desktop/App.axaml
index 3c2bebe..098f598 100644
--- a/demo/Semi.Avalonia.Demo.Desktop/App.axaml
+++ b/demo/Semi.Avalonia.Demo.Desktop/App.axaml
@@ -6,5 +6,6 @@
+
\ No newline at end of file
diff --git a/demo/Semi.Avalonia.Demo/Pages/DataGridDemo.axaml b/demo/Semi.Avalonia.Demo/Pages/DataGridDemo.axaml
new file mode 100644
index 0000000..a007c29
--- /dev/null
+++ b/demo/Semi.Avalonia.Demo/Pages/DataGridDemo.axaml
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/Semi.Avalonia.Demo/Pages/DataGridDemo.axaml.cs b/demo/Semi.Avalonia.Demo/Pages/DataGridDemo.axaml.cs
new file mode 100644
index 0000000..1cdc44b
--- /dev/null
+++ b/demo/Semi.Avalonia.Demo/Pages/DataGridDemo.axaml.cs
@@ -0,0 +1,507 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using Avalonia;
+using Avalonia.Collections;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Data;
+using Avalonia.Markup.Xaml;
+using Avalonia.Threading;
+
+namespace Semi.Avalonia.Demo.Pages;
+
+public partial class DataGridDemo : UserControl
+{
+ public DataGridDemo()
+ {
+ InitializeComponent();
+
+ var dataGridSortDescription = DataGridSortDescription.FromPath(nameof(Country.Region), ListSortDirection.Ascending, new ReversedStringComparer());
+ var collectionView1 = new DataGridCollectionView(Countries.All);
+ collectionView1.SortDescriptions.Add(dataGridSortDescription);
+ var dg1 = this.Get("dataGrid1");
+ dg1.IsReadOnly = true;
+ dg1.LoadingRow += Dg1_LoadingRow;
+ dg1.Sorting += (s, a) =>
+ {
+ var binding = (a.Column as DataGridBoundColumn)?.Binding as Binding;
+
+ if (binding?.Path is string property
+ && property == dataGridSortDescription.PropertyPath
+ && !collectionView1.SortDescriptions.Contains(dataGridSortDescription))
+ {
+ collectionView1.SortDescriptions.Add(dataGridSortDescription);
+ }
+ };
+ dg1.Items = collectionView1;
+
+ var dg2 = this.Get("dataGridGrouping");
+ dg2.IsReadOnly = true;
+
+ var collectionView2 = new DataGridCollectionView(Countries.All);
+ collectionView2.GroupDescriptions.Add(new DataGridPathGroupDescription("Region"));
+
+ dg2.Items = collectionView2;
+
+ var dg3 = this.Get("dataGridEdit");
+ dg3.IsReadOnly = false;
+
+ var list = new ObservableCollection
+ {
+ new Person { FirstName = "John", LastName = "Doe" , Age = 30},
+ new Person { FirstName = "Elizabeth", LastName = "Thomas", IsBanned = true , Age = 40 },
+ new Person { FirstName = "Zack", LastName = "Ward" , Age = 50 }
+ };
+ DataGrid3Source = list;
+
+ var addButton = this.Get