From dfe3b55de802cfef25fae53fe3e968a198f638ad Mon Sep 17 00:00:00 2001 From: Max Katz Date: Mon, 28 Sep 2020 19:28:24 -0400 Subject: [PATCH] DataGrid :empty-rows and :empty-columns pseudoclasses --- src/Avalonia.Controls.DataGrid/DataGrid.cs | 24 +++++++++++- .../DataGridDataConnection.cs | 39 ++++++++++--------- 2 files changed, 43 insertions(+), 20 deletions(-) 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()