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.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/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().Count() ?? 0; - } - } + public int Count => GetCount(true); public bool DataIsPrimitive { @@ -210,6 +193,24 @@ namespace Avalonia.Controls } } + internal bool Any() + { + return GetCount(false) > 0; + } + + /// When "allowSlow" is false, method will not use Linq.Count() method and will return 0 or 1 instead. + private int GetCount(bool allowSlow) + { + return DataSource switch + { + ICollection collection => collection.Count, + DataGridCollectionView cv => cv.Count, + IEnumerable enumerable when allowSlow => enumerable.Cast().Count(), + IEnumerable enumerable when !allowSlow => enumerable.Cast().Any() ? 1 : 0, + _ => 0 + }; + } + /// /// Puts the entity into editing mode if possible /// @@ -675,6 +676,8 @@ namespace Avalonia.Controls } break; } + + _owner.UpdatePseudoClasses(); } private void UpdateDataProperties() diff --git a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml index 30e33c2b2d..998198cc1c 100644 --- a/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml +++ b/src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml @@ -588,18 +588,11 @@ - - + Fill="{DynamicResource DataGridGridLinesBrush}" /> + + + + diff --git a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs index 046b55d49a..7c259f0a09 100644 --- a/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs +++ b/src/Avalonia.Controls/Calendar/CalendarDatePicker.cs @@ -420,7 +420,7 @@ namespace Avalonia.Controls _calendar.DayButtonMouseUp -= Calendar_DayButtonMouseUp; _calendar.DisplayDateChanged -= Calendar_DisplayDateChanged; _calendar.SelectedDatesChanged -= Calendar_SelectedDatesChanged; - _calendar.PointerPressed -= Calendar_PointerPressed; + _calendar.PointerReleased -= Calendar_PointerReleased; _calendar.KeyDown -= Calendar_KeyDown; } _calendar = e.NameScope.Find(ElementCalendar); @@ -435,7 +435,7 @@ namespace Avalonia.Controls _calendar.DayButtonMouseUp += Calendar_DayButtonMouseUp; _calendar.DisplayDateChanged += Calendar_DisplayDateChanged; _calendar.SelectedDatesChanged += Calendar_SelectedDatesChanged; - _calendar.PointerPressed += Calendar_PointerPressed; + _calendar.PointerReleased += Calendar_PointerReleased; _calendar.KeyDown += Calendar_KeyDown; //_calendar.SizeChanged += new SizeChangedEventHandler(Calendar_SizeChanged); //_calendar.IsTabStop = true; @@ -831,9 +831,10 @@ namespace Avalonia.Controls } } } - private void Calendar_PointerPressed(object sender, PointerPressedEventArgs e) + private void Calendar_PointerReleased(object sender, PointerReleasedEventArgs e) { - if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) + + if (e.InitialPressMouseButton == MouseButton.Left) { e.Handled = true; } diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 27313b0b4c..02a9daee75 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -257,7 +257,7 @@ namespace Avalonia.Controls } /// - protected override void OnPointerPressed(PointerPressedEventArgs e) + protected override void OnPointerReleased(PointerReleasedEventArgs e) { if (!e.Handled) { @@ -276,7 +276,7 @@ namespace Avalonia.Controls } } - base.OnPointerPressed(e); + base.OnPointerReleased(e); } /// diff --git a/src/Avalonia.Themes.Default/ComboBox.xaml b/src/Avalonia.Themes.Default/ComboBox.xaml index cced76e850..67151731a8 100644 --- a/src/Avalonia.Themes.Default/ComboBox.xaml +++ b/src/Avalonia.Themes.Default/ComboBox.xaml @@ -26,6 +26,7 @@ + - + - +