Avalonia supports common collection types, but DataTable itself is not a collection and cannot be bound directly. DataTable.Rows and DataTable.DefaultView are collections and can be used as data sources, but DataRow and DataRowView are not standard data types, so the binding engine cannot recognize them correctly. This article records two methods to solve this problem.
Info
Both methods can display data normally. Currently, these two methods do basically the same thing. Method 1 is simpler, while Method 2 may have better support in the future. Please choose as needed.
Both methods use DataRowView because it implements the INotifyPropertyChanged interface, making binding easier.
Tip
If you need grouping, you need to inherit DataGridGroupDescription and write your own grouping logic. The built-in DataGridPathGroupDescription is not very useful.
Tip
Due to the binding implementation of DataGrid, it is always read-only now. If you need to edit, please use template columns or fork Avalonia.Controls.DataGrid for modification.
Warning
Method 1 cannot auto-generate columns. Method 2 theoretically can, but the current DataGrid implementation does not support it yet.
If you want to auto-generate columns, you can currently only choose Behavior or fork Avalonia.Controls.DataGrid for modification.
Danger
Since DataGrid does not support the IBindingList interface, add/delete operations on DataView do not work properly and require additional encapsulation.
Avalonia provides the IPropertyAccessorPlugin interface, which allows you to implement custom property access logic. After implementing a custom property accessor, you can bind cell content by column name.
Avalonia can support dynamic types through the IReflectableType interface. You can simply wrap DataRowView and implement the IReflectableType interface.
Note
DataRowView implements the ICustomTypeDescriptor interface, which means DataRowView itself is a dynamic type, but unfortunately Avalonia does not recognize this interface yet.
Tip
This is just a simple wrapper. In actual use, it may be better to create a dynamic type similar to DataRowView.
Create a type DataRowWrapper that implements the IReflectableType and INotifyPropertyChanged interfaces.
Here, a regular List is used to store DataRowViewWrapper, and the add/delete synchronization logic is not considered.
If needed, you can encapsulate a type similar to DataView yourself.