diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml
index d045626c2c..cacc2204bd 100644
--- a/samples/ControlCatalog/Pages/DataGridPage.xaml
+++ b/samples/ControlCatalog/Pages/DataGridPage.xaml
@@ -11,12 +11,17 @@
-
+
DataGrid
A control for displaying and interacting with a data source.
-
+
+
+
+
+
+
@@ -39,13 +44,13 @@
-
+
-
-
-
+
+
+
diff --git a/src/Avalonia.Animation/KeySplineTypeConverter.cs b/src/Avalonia.Animation/KeySplineTypeConverter.cs
index cd7427a37d..b026206e5f 100644
--- a/src/Avalonia.Animation/KeySplineTypeConverter.cs
+++ b/src/Avalonia.Animation/KeySplineTypeConverter.cs
@@ -19,7 +19,7 @@ namespace Avalonia.Animation
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
- return KeySpline.Parse((string)value, culture);
+ return KeySpline.Parse((string)value, CultureInfo.InvariantCulture);
}
}
}
diff --git a/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs b/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
index 3b61f6d898..f052283b22 100644
--- a/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
+++ b/src/Avalonia.Base/Data/Core/Plugins/DataAnnotationsValidationPlugin.cs
@@ -63,12 +63,12 @@ namespace Avalonia.Data.Core.Plugins
{
if (errors.Count == 1)
{
- return new ValidationException(errors[0].ErrorMessage);
+ return new DataValidationException(errors[0].ErrorMessage);
}
else
{
return new AggregateException(
- errors.Select(x => new ValidationException(x.ErrorMessage)));
+ errors.Select(x => new DataValidationException(x.ErrorMessage)));
}
}
}
diff --git a/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt b/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt
new file mode 100644
index 0000000000..82472c505a
--- /dev/null
+++ b/src/Avalonia.Controls.DataGrid/ApiCompatBaseline.txt
@@ -0,0 +1,5 @@
+Compat issues with assembly Avalonia.Controls.DataGrid:
+MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.DataGridTextColumn.FontFamilyProperty' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public System.String Avalonia.Controls.DataGridTextColumn.FontFamily.get()' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'public void Avalonia.Controls.DataGridTextColumn.FontFamily.set(System.String)' does not exist in the implementation but it does exist in the contract.
+Total Issues: 3
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index 7c57ea3db9..5bb2763566 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -31,7 +31,7 @@ namespace Avalonia.Controls
///
/// Displays data in a customizable grid.
///
- [PseudoClasses(":invalid")]
+ [PseudoClasses(":invalid", ":empty-rows", ":empty-columns")]
public partial class DataGrid : TemplatedControl
{
private const string DATAGRID_elementRowsPresenterName = "PART_RowsPresenter";
@@ -711,6 +711,7 @@ namespace Avalonia.Controls
DisplayData = new DataGridDisplayData(this);
ColumnsInternal = CreateColumnsInstance();
+ ColumnsInternal.CollectionChanged += ColumnsInternal_CollectionChanged;
RowHeightEstimate = DATAGRID_defaultRowHeight;
RowDetailsHeightEstimate = 0;
@@ -727,6 +728,8 @@ namespace Avalonia.Controls
CurrentCellCoordinates = new DataGridCellCoordinates(-1, -1);
RowGroupHeaderHeightEstimate = DATAGRID_defaultRowHeight;
+
+ UpdatePseudoClasses();
}
private void SetValueNoCallback(AvaloniaProperty property, T value, BindingPriority priority = BindingPriority.LocalValue)
@@ -851,9 +854,27 @@ namespace Avalonia.Controls
// can be set when the DataGrid is not part of the visual tree
_measured = false;
InvalidateMeasure();
+
+ UpdatePseudoClasses();
}
}
+ private void ColumnsInternal_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+ {
+ if (e.Action == NotifyCollectionChangedAction.Add
+ || e.Action == NotifyCollectionChangedAction.Remove
+ || e.Action == NotifyCollectionChangedAction.Reset)
+ {
+ UpdatePseudoClasses();
+ }
+ }
+
+ internal void UpdatePseudoClasses()
+ {
+ PseudoClasses.Set(":empty-columns", !ColumnsInternal.GetVisibleColumns().Any());
+ PseudoClasses.Set(":empty-rows", !DataConnection.Any());
+ }
+
private void OnSelectedIndexChanged(AvaloniaPropertyChangedEventArgs e)
{
if (!_areHandlersSuspended)
@@ -1348,7 +1369,6 @@ namespace Avalonia.Controls
internal DataGridColumnCollection ColumnsInternal
{
get;
- private set;
}
internal int AnchorSlot
diff --git a/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs
index f1bbea9949..e2a067ac61 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridCheckBoxColumn.cs
@@ -17,9 +17,7 @@ namespace Avalonia.Controls
///
public class DataGridCheckBoxColumn : DataGridBoundColumn
{
-
private bool _beganEditWithKeyboard;
- private bool _isThreeState;
private CheckBox _currentCheckBox;
private DataGrid _owningGrid;
@@ -31,6 +29,12 @@ namespace Avalonia.Controls
BindingTarget = CheckBox.IsCheckedProperty;
}
+ ///
+ /// Defines the property.
+ ///
+ public static StyledProperty IsThreeStateProperty =
+ CheckBox.IsThreeStateProperty.AddOwner();
+
///
/// Gets or sets a value that indicates whether the hosted controls allow three states or two.
///
@@ -39,17 +43,17 @@ namespace Avalonia.Controls
///
public bool IsThreeState
{
- get
- {
- return _isThreeState;
- }
- set
+ get => GetValue(IsThreeStateProperty);
+ set => SetValue(IsThreeStateProperty, value);
+ }
+
+ protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+ {
+ base.OnPropertyChanged(change);
+
+ if (change.Property == IsThreeStateProperty)
{
- if (_isThreeState != value)
- {
- _isThreeState = value;
- NotifyPropertyChanged(nameof(IsThreeState));
- }
+ NotifyPropertyChanged(change.Property.Name);
}
}
@@ -203,9 +207,9 @@ namespace Avalonia.Controls
{
throw new ArgumentNullException("element");
}
- if(element is CheckBox checkBox)
+ if (element is CheckBox checkBox)
{
- checkBox.IsThreeState = IsThreeState;
+ DataGridHelper.SyncColumnProperty(this, checkBox, IsThreeStateProperty);
}
else
{
@@ -229,7 +233,7 @@ namespace Avalonia.Controls
{
checkBox.HorizontalAlignment = HorizontalAlignment.Center;
checkBox.VerticalAlignment = VerticalAlignment.Center;
- checkBox.IsThreeState = IsThreeState;
+ DataGridHelper.SyncColumnProperty(this, checkBox, IsThreeStateProperty);
}
private bool EnsureOwningGrid()
diff --git a/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs b/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs
index 19539bf032..a94acdec57 100644
--- a/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs
@@ -77,24 +77,7 @@ namespace Avalonia.Controls
private set;
}
- public int Count
- {
- get
- {
- IList list = List;
- if (list != null)
- {
- return list.Count;
- }
-
- if(DataSource is DataGridCollectionView cv)
- {
- return cv.Count;
- }
-
- return DataSource?.Cast