Add Empty DataSource indicator support

This commit is contained in:
chinboy
2025-07-16 12:22:01 +08:00
parent 4900b4217e
commit 59cbb62ca0
6 changed files with 88 additions and 25 deletions
@@ -52,6 +52,12 @@ public partial class DataGrid
o => o.HeaderCornerRadius,
(o, v) => o.HeaderCornerRadius = v);
internal static readonly DirectProperty<DataGrid, bool> IsEmptyDataSourceProperty =
AvaloniaProperty.RegisterDirect<DataGrid, bool>(
nameof(IsEmptyDataSource),
o => o.IsEmptyDataSource,
(o, v) => o.IsEmptyDataSource = v);
internal bool IsGroupHeaderMode
{
get => _isGroupHeaderMode;
@@ -73,6 +79,13 @@ public partial class DataGrid
}
private CornerRadius _headerCornerRadius;
internal bool IsEmptyDataSource
{
get => _isEmptyDataSource;
set => SetAndRaise(IsEmptyDataSourceProperty, ref _isEmptyDataSource, value);
}
private bool _isEmptyDataSource = false;
internal IndexToValueTable<DataGridRowGroupInfo> RowGroupHeadersTable { get; private set; }
internal DataGridDisplayData DisplayData { get; private set; }
@@ -1306,13 +1319,25 @@ public partial class DataGrid
: default;
}
Debug.Assert(newCollectionView != null);
if (newCollectionView.Filter == null)
if (oldCollectionView != null)
{
// TODO 不知道这样循环会不会有内存泄露的风险
_defaultFilter = new DataGridDefaultFilter(newCollectionView);
newCollectionView.Filter = _defaultFilter;
oldCollectionView.CollectionChanged -= HandleDataCollectionViewChanged;
}
if (newCollectionView != null)
{
newCollectionView.CollectionChanged += HandleDataCollectionViewChanged;
IsEmptyDataSource = newCollectionView.IsEmpty;
if (newCollectionView.Filter == null)
{
// TODO 不知道这样循环会不会有内存泄露的风险
_defaultFilter = new DataGridDefaultFilter(newCollectionView);
newCollectionView.Filter = _defaultFilter;
}
}
else
{
IsEmptyDataSource = true;
}
DataConnection.DataSource = newCollectionView;
@@ -1363,6 +1388,14 @@ public partial class DataGrid
}
}
private void HandleDataCollectionViewChanged(object? sender, NotifyCollectionChangedEventArgs args)
{
if (sender is DataGridCollectionView view)
{
IsEmptyDataSource = view.IsEmpty;
}
}
internal void UpdatePseudoClasses()
{
var visibleColumns = ColumnsInternal.GetVisibleColumns().ToList();
+27 -3
View File
@@ -227,6 +227,12 @@ public partial class DataGrid : TemplatedControl,
public static readonly StyledProperty<IDataTemplate?> FooterTemplateProperty =
AvaloniaProperty.Register<DataGrid, IDataTemplate?>(nameof(FooterTemplate));
public static readonly StyledProperty<object?> EmptyIndicatorProperty =
AvaloniaProperty.Register<DataGrid, object?>(nameof(EmptyIndicator));
public static readonly StyledProperty<IDataTemplate?> EmptyIndicatorTemplateProperty =
AvaloniaProperty.Register<DataGrid, IDataTemplate?>(nameof(EmptyIndicatorTemplate));
public static readonly StyledProperty<bool> IsMotionEnabledProperty =
MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner<DataGrid>();
@@ -586,11 +592,24 @@ public partial class DataGrid : TemplatedControl,
get => GetValue(FooterTemplateProperty);
set => SetValue(FooterTemplateProperty, value);
}
[DependsOn(nameof(EmptyIndicatorTemplate))]
public object? EmptyIndicator
{
get => GetValue(EmptyIndicatorProperty);
set => SetValue(EmptyIndicatorProperty, value);
}
public IDataTemplate? EmptyIndicatorTemplate
{
get => GetValue(EmptyIndicatorTemplateProperty);
set => SetValue(EmptyIndicatorTemplateProperty, value);
}
/// <summary>
/// Gets or sets the column that contains the current cell.
/// </summary>
public DataGridColumn? CurrentColumn
/// Gets or sets the column that contains the current cell.
/// </summary>
public DataGridColumn? CurrentColumn
{
get
{
@@ -1530,6 +1549,11 @@ public partial class DataGrid : TemplatedControl,
}
ConfigureHeaderCornerRadius();
SetValue(EmptyIndicatorProperty, new EmptyIndicator()
{
SizeType = SizeType.Middle,
PresetImage = PresetEmptyImage.Simple
}, BindingPriority.Template);
}
/// <summary>
@@ -1,8 +0,0 @@
using Avalonia.Controls.Primitives;
namespace AtomUI.Controls;
internal class DataGridEmptyDataIndicator : TemplatedControl
{
}
@@ -1,7 +0,0 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atom="https://atomui.net">
<ControlTheme x:Key="{x:Type atom:DataGridEmptyDataIndicator}" TargetType="atom:DataGridEmptyDataIndicator">
</ControlTheme>
</ResourceDictionary>
@@ -67,7 +67,8 @@
Grid.Column="0"
Grid.RowSpan="2"
Grid.ColumnSpan="3"
ScrollViewer.IsScrollInertiaEnabled="{TemplateBinding IsScrollInertiaEnabled}">
ScrollViewer.IsScrollInertiaEnabled="{TemplateBinding IsScrollInertiaEnabled}"
IsVisible="{TemplateBinding IsEmptyDataSource, Converter={x:Static BoolConverters.Not}}">
<atom:DataGridRowsPresenter.GestureRecognizers>
<ScrollGestureRecognizer
CanHorizontallyScroll="True"
@@ -75,6 +76,20 @@
IsScrollInertiaEnabled="{Binding (ScrollViewer.IsScrollInertiaEnabled), ElementName=PART_RowPresenter}" />
</atom:DataGridRowsPresenter.GestureRecognizers>
</atom:DataGridRowsPresenter>
<ContentPresenter
Name="{x:Static atom:DataGridThemeConstants.EmptyIndicatorPart}"
Grid.Row="1"
Grid.Column="0"
Grid.RowSpan="2"
Grid.ColumnSpan="3"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
IsVisible="{TemplateBinding IsEmptyDataSource}"
Content="{TemplateBinding EmptyIndicator}"
ContentTemplate="{TemplateBinding EmptyIndicatorTemplate}"
/>
<Rectangle
Name="{x:Static atom:DataGridThemeConstants.BottomRightCornerPart}"
Grid.Row="2"
@@ -143,6 +158,11 @@
<Setter Property="Background" Value="{DynamicResource {x:Static atom:DataGridTokenKey.TableFooterBg}}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_EmptyIndicator">
<Setter Property="Padding"
Value="{DynamicResource {x:Static atom:SharedTokenKey.PaddingXL}}" />
</Style>
<Style Selector="^[SizeType=Large]">
<Style Selector="^ /template/ ContentPresenter#PART_Title">
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:DataGridTokenKey.TablePadding}}" />
@@ -88,6 +88,7 @@ internal static class DataGridSortIndicatorThemeConstants
internal static class DataGridThemeConstants
{
public const string RowsPresenterPart = "PART_RowPresenter";
public const string EmptyIndicatorPart = "PART_EmptyIndicator";
public const string ColumnHeadersPresenterPart = "PART_ColumnHeadersPresenter";
public const string GroupColumnHeadersPresenterPart = "PART_GroupColumnHeadersPresenter";
public const string HorizontalScrollbarPart = "PART_HorizontalScrollbar";