Add SizeType Support for DataGrid

This commit is contained in:
CHINBOY
2025-05-30 11:23:22 +08:00
parent d58b4c4424
commit b577eb734f
12 changed files with 133 additions and 39 deletions
@@ -34,6 +34,15 @@ public class DataGridCell : ContentControl
#endregion
#region 内部属性定义
internal static readonly StyledProperty<SizeType> SizeTypeProperty =
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<DataGridCell>();
internal SizeType SizeType
{
get => GetValue(SizeTypeProperty);
set => SetValue(SizeTypeProperty, value);
}
internal DataGridRow? OwningRow { get; set; }
@@ -66,10 +66,7 @@ public abstract partial class DataGridColumn
{
get
{
if (_headerCell == null)
{
_headerCell = CreateHeader();
}
_headerCell ??= CreateHeader();;
return _headerCell;
}
}
@@ -239,9 +236,10 @@ public abstract partial class DataGridColumn
{
OwningColumn = this
};
Debug.Assert(OwningGrid != null);
result[!ContentControl.ContentProperty] = this[!HeaderProperty];
result[!ContentControl.ContentTemplateProperty] = this[!HeaderTemplateProperty];
Debug.Assert(OwningGrid != null);
result[!DataGridColumnHeader.SizeTypeProperty] = OwningGrid[!DataGrid.SizeTypeProperty];
// TODO 需要审查,原则上我们 AtomUI 是不允许整体自定义的
if (OwningGrid.ColumnHeaderTheme is { } columnTheme)
{
@@ -64,6 +64,15 @@ public class DataGridColumnHeader : ContentControl
#endregion
#region 内部属性定义
internal static readonly StyledProperty<SizeType> SizeTypeProperty =
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<DataGridColumnHeader>();
internal SizeType SizeType
{
get => GetValue(SizeTypeProperty);
set => SetValue(SizeTypeProperty, value);
}
internal DataGridColumn? OwningColumn { get; set; }
@@ -8,8 +8,10 @@ using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Reactive.Disposables;
using AtomUI.Controls.Data;
using AtomUI.Controls.Utils;
using AtomUI.Theme;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
@@ -161,6 +163,12 @@ public partial class DataGrid
internal ScrollBar? VerticalScrollBar => _vScrollBar;
internal ScrollBar? HorizontalScrollBar => _hScrollBar;
Control IMotionAwareControl.PropertyBindTarget => this;
Control IControlSharedTokenResourcesHost.HostControl => this;
string IControlSharedTokenResourcesHost.TokenId => DataGridToken.ID;
CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable;
private CompositeDisposable? _resourceBindingsDisposable;
#endregion
@@ -173,8 +181,7 @@ public partial class DataGrid
/// some properties to be ordered at the beginning and some at the end.
/// </remarks>
private const int DefaultColumnDisplayOrder = 10000;
internal const double HorizontalGridLinesThickness = 1;
private const double MinimumRowHeaderWidth = 4;
private const double MinimumColumnHeaderHeight = 4;
internal const double MaximumStarColumnWidth = 10000;
+51 -14
View File
@@ -6,7 +6,12 @@
using System.Collections;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reactive.Disposables;
using AtomUI.Controls.Data;
using AtomUI.Theme;
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
@@ -32,10 +37,17 @@ namespace AtomUI.Controls;
[TemplatePart(DataGridTheme.TopRightCornerPart, typeof(ContentControl))]
[TemplatePart(DataGridTheme.VerticalScrollbarPart, typeof(ScrollBar))]
[PseudoClasses(StdPseudoClass.Invalid, DataGridPseudoClass.EmptyRows, DataGridPseudoClass.EmptyColumns)]
public partial class DataGrid : TemplatedControl
public partial class DataGrid : TemplatedControl,
ISizeTypeAware,
IMotionAwareControl,
IControlSharedTokenResourcesHost,
IResourceBindingManager
{
#region 公共属性定义
public static readonly StyledProperty<SizeType> SizeTypeProperty =
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<DataGrid>();
/// <summary>
/// Identifies the CanUserReorderColumns dependency property.
/// </summary>
@@ -107,6 +119,9 @@ public partial class DataGrid : TemplatedControl
public static readonly StyledProperty<IBrush?> HorizontalGridLinesBrushProperty =
AvaloniaProperty.Register<DataGrid, IBrush?>(nameof(HorizontalGridLinesBrush));
public static readonly StyledProperty<IBrush?> VerticalGridLinesBrushProperty =
AvaloniaProperty.Register<DataGrid, IBrush?>(nameof(VerticalGridLinesBrush));
public static readonly StyledProperty<ScrollBarVisibility> HorizontalScrollBarVisibilityProperty =
AvaloniaProperty.Register<DataGrid, ScrollBarVisibility>(nameof(HorizontalScrollBarVisibility));
@@ -159,9 +174,6 @@ public partial class DataGrid : TemplatedControl
public static readonly StyledProperty<DataGridSelectionMode> SelectionModeProperty =
AvaloniaProperty.Register<DataGrid, DataGridSelectionMode>(nameof(SelectionMode));
public static readonly StyledProperty<IBrush?> VerticalGridLinesBrushProperty =
AvaloniaProperty.Register<DataGrid, IBrush?>(nameof(VerticalGridLinesBrush));
public static readonly StyledProperty<ScrollBarVisibility> VerticalScrollBarVisibilityProperty =
AvaloniaProperty.Register<DataGrid, ScrollBarVisibility>(nameof(VerticalScrollBarVisibility));
@@ -209,6 +221,15 @@ public partial class DataGrid : TemplatedControl
AvaloniaProperty.RegisterDirect<DataGrid, IDataGridCollectionView?>(nameof(CollectionView),
o => o.CollectionView);
public static readonly StyledProperty<bool> IsMotionEnabledProperty
= WaveSpiritAwareControlProperty.IsMotionEnabledProperty.AddOwner<DataGrid>();
public SizeType SizeType
{
get => GetValue(SizeTypeProperty);
set => SetValue(SizeTypeProperty, value);
}
/// <summary>
/// Gets or sets a value that indicates whether the user can change
/// the column display order by dragging column headers with the mouse.
@@ -327,6 +348,15 @@ public partial class DataGrid : TemplatedControl
set => SetValue(HorizontalGridLinesBrushProperty, value);
}
/// <summary>
/// Gets or sets the <see cref="T:System.Windows.Media.Brush" /> that is used to paint grid lines separating columns.
/// </summary>
public IBrush? VerticalGridLinesBrush
{
get => GetValue(VerticalGridLinesBrushProperty);
set => SetValue(VerticalGridLinesBrushProperty, value);
}
/// <summary>
/// Gets or sets a value that indicates how the horizontal scroll bar is displayed.
/// </summary>
@@ -437,15 +467,6 @@ public partial class DataGrid : TemplatedControl
get => GetValue(SelectionModeProperty);
set => SetValue(SelectionModeProperty, value);
}
/// <summary>
/// Gets or sets the <see cref="T:System.Windows.Media.Brush" /> that is used to paint grid lines separating columns.
/// </summary>
public IBrush? VerticalGridLinesBrush
{
get => GetValue(VerticalGridLinesBrushProperty);
set => SetValue(VerticalGridLinesBrushProperty, value);
}
/// <summary>
/// Gets or sets the template that is used when rendering the column headers.
@@ -617,7 +638,13 @@ public partial class DataGrid : TemplatedControl
/// <summary>
/// Gets a list that contains the data items corresponding to the selected rows.
/// </summary>
public IList SelectedItems => _selectedItems as IList;
public IList SelectedItems => _selectedItems;
public bool IsMotionEnabled
{
get => GetValue(IsMotionEnabledProperty);
set => SetValue(IsMotionEnabledProperty, value);
}
#endregion
@@ -814,6 +841,8 @@ public partial class DataGrid : TemplatedControl
HorizontalScrollBarVisibilityProperty,
VerticalScrollBarVisibilityProperty);
SizeTypeProperty.OverrideDefaultValue<DataGrid>(SizeType.Large);
ItemsSourceProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.HandleItemsSourcePropertyChanged(e));
CanUserResizeColumnsProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.HandleCanUserResizeColumnsChanged(e));
ColumnWidthProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.HandleColumnWidthChanged(e));
@@ -841,6 +870,8 @@ public partial class DataGrid : TemplatedControl
public DataGrid()
{
this.RegisterResources();
this.BindMotionProperties();
KeyDown += HandleKeyDown;
KeyUp += HandleKeyUp;
@@ -875,6 +906,7 @@ public partial class DataGrid : TemplatedControl
RowGroupHeaderHeightEstimate = DefaultRowHeight;
RowGroupSublevelIndents = [];
_rowGroupHeightsByLevel = [];
_resourceBindingsDisposable = new CompositeDisposable();
UpdatePseudoClasses();
}
@@ -1030,6 +1062,10 @@ public partial class DataGrid : TemplatedControl
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
this.AddResourceBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, BorderThicknessProperty,
SharedTokenKey.BorderThickness,
BindingPriority.Template,
new RenderScaleAwareThicknessConfigure(this)));
if (DataConnection.DataSource != null && !DataConnection.EventsWired)
{
DataConnection.WireEvents(DataConnection.DataSource);
@@ -1045,6 +1081,7 @@ public partial class DataGrid : TemplatedControl
{
DataConnection.UnWireEvents(DataConnection.DataSource);
}
this.DisposeTokenBindings();
}
/// <summary>
@@ -48,7 +48,8 @@ public partial class DataGridRow
if (_bottomGridLine != null && OwningGrid != null && OwningGrid.AreRowBottomGridLinesRequired)
{
// Unfortunately, _bottomGridLine has no size yet so we can't get its actualheight
return DataGrid.HorizontalGridLinesThickness;
// TODO 需要审查这里不是常量可以吗?是不是会导致高度计算错误
return OwningGrid.BorderThickness.Left;
}
return 0;
}
@@ -5,6 +5,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
using Avalonia.Media;
using Avalonia.Styling;
using HorizontalAlignment = Avalonia.Layout.HorizontalAlignment;
using VerticalAlignment = Avalonia.Layout.VerticalAlignment;
@@ -131,4 +132,13 @@ internal class DataGridCellTheme : BaseControlTheme
Grid.SetColumn(focusVisualLayout, 0);
rootLayout.Children.Add(focusVisualLayout);
}
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(DataGridCell.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
commonStyle.Add(DataGridCell.VerticalAlignmentProperty, VerticalAlignment.Stretch);
commonStyle.Add(DataGridCell.FocusableProperty, false);
Add(commonStyle);
}
}
@@ -1,3 +1,4 @@
using AtomUI.IconPkg;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Controls;
@@ -6,6 +7,7 @@ using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Styling;
namespace AtomUI.Controls;
@@ -39,6 +41,7 @@ internal class DataGridColumnHeaderTheme : BaseControlTheme
{
Name = HeaderFramePart
};
CreateTemplateParentBinding(headerFrame, Border.BackgroundProperty, DataGridColumnHeader.BackgroundProperty);
var headerRootLayout = new Grid
{
@@ -70,7 +73,6 @@ internal class DataGridColumnHeaderTheme : BaseControlTheme
private void BuildContentPresenter(Grid rootLayout)
{
var contentPresenterLayout = new Panel();
var gridLayout = new Grid()
{
ColumnDefinitions =
@@ -79,7 +81,8 @@ internal class DataGridColumnHeaderTheme : BaseControlTheme
new ColumnDefinition(GridLength.Auto),
]
};
CreateTemplateParentBinding(gridLayout, Grid.HorizontalAlignmentProperty, DataGridColumnHeader.HorizontalAlignmentProperty);
CreateTemplateParentBinding(gridLayout, Grid.VerticalAlignmentProperty, DataGridColumnHeader.VerticalAlignmentProperty);
var contentPresenter = new ContentPresenter()
{
Name = ContentPresenterPart,
@@ -89,27 +92,24 @@ internal class DataGridColumnHeaderTheme : BaseControlTheme
Grid.SetColumn(contentPresenter, 0);
gridLayout.Children.Add(contentPresenter);
var iconPresenter = new ContentPresenter()
var iconPresenter = new IconPresenter()
{
Name = SortIconPresenterPart,
IsVisible = false,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
IsVisible = false
};
Grid.SetColumn(iconPresenter, 1);
gridLayout.Children.Add(iconPresenter);
contentPresenterLayout.Children.Add(gridLayout);
Grid.SetColumn(rootLayout, 0);
rootLayout.Children.Add(contentPresenterLayout);
Grid.SetColumn(gridLayout, 0);
rootLayout.Children.Add(gridLayout);
}
private void BuildFocusVisual(Grid rootLayout)
{
var focusVisualLayout = new Grid()
var focusVisualLayout = new Panel()
{
IsVisible = false,
Name = FocusVisualPart,
Name = FocusVisualPart,
IsVisible = false,
IsHitTestVisible = false,
};
@@ -138,4 +138,15 @@ internal class DataGridColumnHeaderTheme : BaseControlTheme
Grid.SetColumn(focusVisualLayout, 0);
rootLayout.Children.Add(focusVisualLayout);
}
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(DataGridColumnHeader.ForegroundProperty, DataGridTokenKey.TableHeaderTextColor);
commonStyle.Add(DataGridColumnHeader.BackgroundProperty, DataGridTokenKey.TableHeaderBg);
commonStyle.Add(DataGridColumnHeader.FontWeightProperty, SharedTokenKey.FontWeightStrong);
commonStyle.Add(DataGridColumnHeader.HorizontalContentAlignmentProperty, HorizontalAlignment.Left);
commonStyle.Add(DataGridColumnHeader.VerticalContentAlignmentProperty, VerticalAlignment.Center);
Add(commonStyle);
}
}
@@ -6,6 +6,8 @@ using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Layout;
using Avalonia.Styling;
@@ -82,8 +84,11 @@ internal class DataGridTheme : BaseControlTheme
{
Name = ColumnHeadersAndRowsSeparatorPart,
VerticalAlignment = VerticalAlignment.Bottom,
Height = 1
};
CreateTemplateParentBinding(columnHeadersAndRowsSeparator, Rectangle.HeightProperty, DataGrid.BorderThicknessProperty,
BindingMode.Default, new FuncValueConverter<Thickness, double>(thickness => thickness.Left));
Grid.SetRow(columnHeadersAndRowsSeparator, 0);
Grid.SetColumn(columnHeadersAndRowsSeparator, 0);
Grid.SetColumnSpan(columnHeadersAndRowsSeparator, 3);
@@ -188,6 +193,13 @@ internal class DataGridTheme : BaseControlTheme
commonStyle.Add(DataGrid.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Auto);
commonStyle.Add(DataGrid.SelectionModeProperty, DataGridSelectionMode.Extended);
commonStyle.Add(DataGrid.FocusAdornerProperty, null);
commonStyle.Add(DataGrid.HorizontalGridLinesBrushProperty, DataGridTokenKey.TableBorderColor);
commonStyle.Add(DataGrid.VerticalGridLinesBrushProperty, DataGridTokenKey.TableBorderColor);
var columnHeadersAndRowsSeparatorStyle = new Style(selector => selector.Nesting().Template().Name(ColumnHeadersAndRowsSeparatorPart));
columnHeadersAndRowsSeparatorStyle.Add(Rectangle.FillProperty, DataGridTokenKey.TableBorderColor);
commonStyle.Add(columnHeadersAndRowsSeparatorStyle);
Add(commonStyle);
}
}
@@ -6,7 +6,7 @@ using Avalonia.VisualTree;
namespace AtomUI.Theme.Data;
internal class RenderScaleAwareThicknessConfigure
public class RenderScaleAwareThicknessConfigure
{
private readonly WeakReference<Control> _control;
private readonly Func<Thickness, Thickness>? _postProcessor;
@@ -2,7 +2,7 @@ using Avalonia.Controls;
namespace AtomUI.Theme;
internal interface IControlSharedTokenResourcesHost
public interface IControlSharedTokenResourcesHost
{
Control HostControl { get; }
string TokenId { get; }
@@ -5,7 +5,7 @@ using Avalonia.LogicalTree;
namespace AtomUI.Theme.Utils;
internal static class ControlSharedTokenResourcesHostExtensions
public static class ControlSharedTokenResourcesHostExtensions
{
public static void RegisterResources(this IControlSharedTokenResourcesHost host)
{