Add DataGridCell

This commit is contained in:
CHINBOY
2025-05-28 22:55:27 +08:00
parent 4d144008af
commit cccf90193e
6 changed files with 627 additions and 9 deletions
@@ -1,8 +1,232 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
namespace AtomUI.Controls;
[TemplatePart(DataGridCellTheme.RightGridLinePart, typeof(Rectangle))]
[PseudoClasses(StdPseudoClass.Selected, StdPseudoClass.Current, StdPseudoClass.Edited, StdPseudoClass.Invalid, StdPseudoClass.Focus)]
public class DataGridCell : ContentControl
{
#region 公共属性定义
public static readonly DirectProperty<DataGridCell, bool> IsValidProperty =
AvaloniaProperty.RegisterDirect<DataGridCell, bool>(
nameof(IsValid),
o => o.IsValid);
bool _isValid = true;
public bool IsValid
{
get => _isValid;
internal set => SetAndRaise(IsValidProperty, ref _isValid, value);
}
#endregion
#region 内部属性定义
internal DataGridRow? OwningRow { get; set; }
private DataGridColumn? _owningColumn;
internal DataGridColumn? OwningColumn
{
get => _owningColumn;
set
{
if (_owningColumn != value)
{
_owningColumn = value;
OnOwningColumnSet(value);
}
}
}
internal DataGrid? OwningGrid => OwningRow?.OwningGrid ?? OwningColumn?.OwningGrid;
internal double ActualRightGridLineWidth => _rightGridLine?.Bounds.Width ?? 0;
internal int ColumnIndex => OwningColumn?.Index ?? -1;
internal int RowIndex => OwningRow?.Index ?? -1;
internal bool IsCurrent => OwningGrid != null &&
OwningColumn != null &&
OwningRow != null &&
OwningGrid.CurrentColumnIndex == OwningColumn.Index &&
OwningGrid.CurrentSlot == OwningRow.Slot;
private bool IsEdited => OwningGrid != null &&
OwningGrid.EditingRow == OwningRow &&
OwningGrid.EditingColumnIndex == ColumnIndex;
private bool IsMouseOver
{
get => OwningRow != null && OwningRow.MouseOverColumnIndex == ColumnIndex;
set
{
Debug.Assert(OwningRow != null);
if (value != IsMouseOver)
{
if (value)
{
OwningRow.MouseOverColumnIndex = ColumnIndex;
}
else
{
OwningRow.MouseOverColumnIndex = null;
}
}
}
}
#endregion
private Rectangle? _rightGridLine;
/// <summary>
/// Builds the visual tree for the cell control when a new template is applied.
/// </summary>
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
UpdatePseudoClasses();
_rightGridLine = e.NameScope.Find<Rectangle>(DataGridCellTheme.RightGridLinePart);
if (_rightGridLine != null && OwningColumn == null)
{
// Turn off the right GridLine for filler cells
_rightGridLine.IsVisible = false;
}
else
{
EnsureGridLine(null);
}
}
protected override void OnPointerEntered(PointerEventArgs e)
{
base.OnPointerEntered(e);
if (OwningRow != null)
{
IsMouseOver = true;
}
}
protected override void OnPointerExited(PointerEventArgs e)
{
base.OnPointerExited(e);
if (OwningRow != null)
{
IsMouseOver = false;
}
}
//TODO TabStop
private void HandlePointerPressed(PointerPressedEventArgs e)
{
// OwningGrid is null for TopLeftHeaderCell and TopRightHeaderCell because they have no OwningRow
if (OwningGrid == null || OwningColumn == null || OwningRow == null)
{
return;
}
OwningGrid.NotifyCellPointerPressed(new DataGridCellPointerPressedEventArgs(this, OwningRow, OwningColumn, e));
if (e.Handled)
{
return;
}
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
if (OwningGrid.IsTabStop)
{
OwningGrid.Focus();
}
if (OwningRow != null)
{
var handled = OwningGrid.UpdateStateOnMouseLeftButtonDown(e, ColumnIndex, OwningRow.Slot, !e.Handled);
// Do not handle PointerPressed with touch or pen,
// so we can start scroll gesture on the same event.
if (e.Pointer.Type != PointerType.Touch && e.Pointer.Type != PointerType.Pen)
{
e.Handled = handled;
}
}
}
else if (e.GetCurrentPoint(this).Properties.IsRightButtonPressed)
{
if (OwningGrid.IsTabStop)
{
OwningGrid.Focus();
}
if (OwningRow != null)
{
e.Handled = OwningGrid.UpdateStateOnMouseRightButtonDown(e, ColumnIndex, OwningRow.Slot, !e.Handled);
}
}
}
internal void UpdatePseudoClasses()
{
if (OwningGrid == null || OwningColumn == null || OwningRow == null || !OwningRow.IsVisible || OwningRow.Slot == -1)
{
return;
}
PseudoClasses.Set(":selected", OwningRow.IsSelected);
PseudoClasses.Set(":current", IsCurrent);
PseudoClasses.Set(":edited", IsEdited);
PseudoClasses.Set(":invalid", !IsValid);
PseudoClasses.Set(":focus", OwningGrid.IsFocused && IsCurrent);
}
// Makes sure the right gridline has the proper stroke and visibility. If lastVisibleColumn is specified, the
// right gridline will be collapsed if this cell belongs to the lastVisibleColumn and there is no filler column
internal void EnsureGridLine(DataGridColumn? lastVisibleColumn)
{
if (OwningGrid != null && _rightGridLine != null)
{
if (OwningGrid.VerticalGridLinesBrush != null && OwningGrid.VerticalGridLinesBrush != _rightGridLine.Fill)
{
_rightGridLine.Fill = OwningGrid.VerticalGridLinesBrush;
}
bool newVisibility =
(OwningGrid.GridLinesVisibility == DataGridGridLinesVisibility.Vertical || OwningGrid.GridLinesVisibility == DataGridGridLinesVisibility.All)
&& ((OwningGrid.ColumnsInternal.FillerColumn != null && OwningGrid.ColumnsInternal.FillerColumn.IsActive) || OwningColumn != lastVisibleColumn);
if (newVisibility != _rightGridLine.IsVisible)
{
_rightGridLine.IsVisible = newVisibility;
}
}
}
private void OnOwningColumnSet(DataGridColumn? column)
{
if (column == null)
{
Classes.Clear();
ClearValue(ThemeProperty);
}
else
{
if (Theme != column.CellTheme)
{
Theme = column.CellTheme;
}
Classes.Replace(column.CellStyleClasses);
}
}
}
@@ -1,9 +1,344 @@
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using System.Collections.Specialized;
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Utilities;
namespace AtomUI.Controls.Cell;
public sealed class DataGridCellsPresenter : Panel, IChildIndexProvider
{
internal DataGrid? OwningGrid => OwningRow?.OwningGrid;
internal DataGridRow? OwningRow { get; set; }
event EventHandler<ChildIndexChangedEventArgs>? IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
}
private double _fillerLeftEdge;
private EventHandler<ChildIndexChangedEventArgs>? _childIndexChanged;
// The desired height needs to be cached due to column virtualization; otherwise, the cells
// would grow and shrink as the DataGrid scrolls horizontally
private double _desiredHeight;
int IChildIndexProvider.GetChildIndex(ILogical child)
{
return child is DataGridCell cell
? cell.OwningColumn?.DisplayIndex ?? -1
: throw new InvalidOperationException("Invalid cell type");
}
bool IChildIndexProvider.TryGetTotalCount(out int count)
{
count = Children.Count - 1; // Adjust for filler column
return true;
}
/// <summary>
/// Arranges the content of the <see cref="T:Avalonia.Controls.Primitives.DataGridCellsPresenter" />.
/// </summary>
/// <returns>
/// The actual size used by the <see cref="T:Avalonia.Controls.Primitives.DataGridCellsPresenter" />.
/// </returns>
/// <param name="finalSize">
/// The final area within the parent that this element should use to arrange itself and its children.
/// </param>
protected override Size ArrangeOverride(Size finalSize)
{
if (OwningGrid == null)
{
return base.ArrangeOverride(finalSize);
}
Debug.Assert(OwningRow != null);
if (OwningGrid.AutoSizingColumns)
{
// When we initially load an auto-column, we have to wait for all the rows to be measured
// before we know its final desired size. We need to trigger a new round of measures now
// that the final sizes have been calculated.
OwningGrid.AutoSizingColumns = false;
return base.ArrangeOverride(finalSize);
}
double frozenLeftEdge = 0;
double scrollingLeftEdge = -OwningGrid.HorizontalOffset;
double cellLeftEdge;
foreach (DataGridColumn column in OwningGrid.ColumnsInternal.GetVisibleColumns())
{
DataGridCell cell = OwningRow.Cells[column.Index];
Debug.Assert(cell.OwningColumn == column);
Debug.Assert(column.IsVisible);
if (column.IsFrozen)
{
cellLeftEdge = frozenLeftEdge;
// This can happen before or after clipping because frozen cells aren't clipped
frozenLeftEdge += column.ActualWidth;
}
else
{
cellLeftEdge = scrollingLeftEdge;
}
if (cell.IsVisible)
{
cell.Arrange(new Rect(cellLeftEdge, 0, column.LayoutRoundedWidth, finalSize.Height));
EnsureCellClip(cell, column.ActualWidth, finalSize.Height, frozenLeftEdge, scrollingLeftEdge);
}
scrollingLeftEdge += column.ActualWidth;
column.IsInitialDesiredWidthDetermined = true;
}
_fillerLeftEdge = scrollingLeftEdge;
Debug.Assert(OwningGrid.ColumnsInternal.FillerColumn != null);
OwningRow.FillerCell.Arrange(new Rect(_fillerLeftEdge, 0, OwningGrid.ColumnsInternal.FillerColumn.FillerWidth, finalSize.Height));
return finalSize;
}
private static void EnsureCellClip(DataGridCell cell, double width, double height, double frozenLeftEdge, double cellLeftEdge)
{
// Clip the cell only if it's scrolled under frozen columns. Unfortunately, we need to clip in this case
// because cells could be transparent
if (cell.OwningColumn != null && !cell.OwningColumn.IsFrozen && frozenLeftEdge > cellLeftEdge)
{
RectangleGeometry rg = new RectangleGeometry();
double xClip = Math.Round(Math.Min(width, frozenLeftEdge - cellLeftEdge));
rg.Rect = new Rect(xClip, 0, Math.Max(0, width - xClip), height);
cell.Clip = rg;
}
else
{
cell.Clip = null;
}
}
protected override void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
base.ChildrenChanged(sender, e);
InvalidateChildIndex();
}
private static void EnsureCellDisplay(DataGridCell cell, bool displayColumn)
{
if (cell.IsCurrent)
{
if (displayColumn)
{
cell.IsVisible = true;
cell.Clip = null;
}
else
{
// Clip
RectangleGeometry rg = new RectangleGeometry();
rg.Rect = default;
cell.Clip = rg;
}
}
else
{
cell.IsVisible = displayColumn;
}
}
internal void EnsureFillerVisibility()
{
Debug.Assert(OwningGrid != null);
Debug.Assert(OwningRow != null);
DataGridFillerColumn? fillerColumn = OwningGrid.ColumnsInternal.FillerColumn;
Debug.Assert(fillerColumn != null);
bool newVisibility = fillerColumn.IsActive;
if (OwningRow.FillerCell.IsVisible != newVisibility)
{
OwningRow.FillerCell.IsVisible = newVisibility;
if (newVisibility)
{
OwningRow.FillerCell.Arrange(new Rect(_fillerLeftEdge, 0, fillerColumn.FillerWidth, Bounds.Height));
}
}
// This must be done after the Filler visibility is determined. This also must be done
// regardless of whether or not the filler visibility actually changed values because
// we could scroll in a cell that didn't have EnsureGridLine called yet
DataGridColumn? lastVisibleColumn = OwningGrid.ColumnsInternal.LastVisibleColumn;
if (lastVisibleColumn != null)
{
DataGridCell cell = OwningRow.Cells[lastVisibleColumn.Index];
cell.EnsureGridLine(lastVisibleColumn);
}
}
/// <summary>
/// Measures the children of a <see cref="T:Avalonia.Controls.Primitives.DataGridCellsPresenter" /> to
/// prepare for arranging them during the <see cref="M:System.Windows.FrameworkElement.ArrangeOverride(System.Windows.Size)" /> pass.
/// </summary>
/// <param name="availableSize">
/// The available size that this element can give to child elements. Indicates an upper limit that child elements should not exceed.
/// </param>
/// <returns>
/// The size that the <see cref="T:Avalonia.Controls.Primitives.DataGridCellsPresenter" /> determines it needs during layout, based on its calculations of child object allocated sizes.
/// </returns>
protected override Size MeasureOverride(Size availableSize)
{
if (OwningGrid == null || OwningRow == null)
{
return base.MeasureOverride(availableSize);
}
bool autoSizeHeight;
double measureHeight;
if (double.IsNaN(OwningGrid.RowHeight))
{
// No explicit height values were set so we can autosize
autoSizeHeight = true;
// We need to invalidate desired height in order to grow or shrink as needed
InvalidateDesiredHeight();
measureHeight = double.PositiveInfinity;
}
else
{
_desiredHeight = OwningGrid.RowHeight;
measureHeight = _desiredHeight;
autoSizeHeight = false;
}
double frozenLeftEdge = 0;
double totalDisplayWidth = 0;
double scrollingLeftEdge = -OwningGrid.HorizontalOffset;
OwningGrid.ColumnsInternal.EnsureVisibleEdgedColumnsWidth();
DataGridColumn? lastVisibleColumn = OwningGrid.ColumnsInternal.LastVisibleColumn;
foreach (DataGridColumn column in OwningGrid.ColumnsInternal.GetVisibleColumns())
{
DataGridCell cell = OwningRow.Cells[column.Index];
// Measure the entire first row to make the horizontal scrollbar more accurate
bool shouldDisplayCell = ShouldDisplayCell(column, frozenLeftEdge, scrollingLeftEdge) || OwningRow.Index == 0;
EnsureCellDisplay(cell, shouldDisplayCell);
if (shouldDisplayCell)
{
DataGridLength columnWidth = column.Width;
bool autoGrowWidth = columnWidth.IsSizeToCells || columnWidth.IsAuto;
if (column != lastVisibleColumn)
{
cell.EnsureGridLine(lastVisibleColumn);
}
// If we're not using star sizing or the current column can't be resized,
// then just set the display width according to the column's desired width
if (!OwningGrid.UsesStarSizing || (!column.ActualCanUserResize && !column.Width.IsStar))
{
// In the edge-case where we're given infinite width and we have star columns, the
// star columns grow to their predefined limit of 10,000 (or their MaxWidth)
double newDisplayWidth = column.Width.IsStar ?
Math.Min(column.ActualMaxWidth, DataGrid.MaximumStarColumnWidth) :
Math.Max(column.ActualMinWidth, Math.Min(column.ActualMaxWidth, column.Width.DesiredValue));
column.SetWidthDisplayValue(newDisplayWidth);
}
// If we're auto-growing the column based on the cell content, we want to measure it at its maximum value
if (autoGrowWidth)
{
cell.Measure(new Size(column.ActualMaxWidth, measureHeight));
OwningGrid.AutoSizeColumn(column, cell.DesiredSize.Width);
column.ComputeLayoutRoundedWidth(totalDisplayWidth);
}
else if (!OwningGrid.UsesStarSizing)
{
column.ComputeLayoutRoundedWidth(scrollingLeftEdge);
cell.Measure(new Size(column.LayoutRoundedWidth, measureHeight));
}
// We need to track the largest height in order to auto-size
if (autoSizeHeight)
{
_desiredHeight = Math.Max(_desiredHeight, cell.DesiredSize.Height);
}
}
if (column.IsFrozen)
{
frozenLeftEdge += column.ActualWidth;
}
scrollingLeftEdge += column.ActualWidth;
totalDisplayWidth += column.ActualWidth;
}
// If we're using star sizing (and we're not waiting for an auto-column to finish growing)
// then we will resize all the columns to fit the available space.
if (OwningGrid.UsesStarSizing && !OwningGrid.AutoSizingColumns)
{
double adjustment = OwningGrid.CellsWidth - totalDisplayWidth;
totalDisplayWidth += adjustment - OwningGrid.AdjustColumnWidths(0, adjustment, false);
// Since we didn't know the final widths of the columns until we resized,
// we waited until now to measure each cell
double leftEdge = 0;
if (autoSizeHeight)
_desiredHeight = 0;
foreach (DataGridColumn column in OwningGrid.ColumnsInternal.GetVisibleColumns())
{
DataGridCell cell = OwningRow.Cells[column.Index];
column.ComputeLayoutRoundedWidth(leftEdge);
cell.Measure(new Size(column.LayoutRoundedWidth, measureHeight));
if (autoSizeHeight)
{
_desiredHeight = Math.Max(_desiredHeight, cell.DesiredSize.Height);
}
leftEdge += column.ActualWidth;
}
}
// Measure FillerCell, we're doing it unconditionally here because we don't know if we'll need the filler
// column and we don't want to cause another Measure if we do
OwningRow.FillerCell.Measure(new Size(double.PositiveInfinity, _desiredHeight));
OwningGrid.ColumnsInternal.EnsureVisibleEdgedColumnsWidth();
return new Size(OwningGrid.ColumnsInternal.VisibleEdgedColumnsWidth, _desiredHeight);
}
internal void Recycle()
{
// Clear out the cached desired height so it is not reused for other rows
_desiredHeight = 0;
}
internal void InvalidateDesiredHeight()
{
_desiredHeight = 0;
}
internal void InvalidateChildIndex()
{
_childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.ChildIndexesReset);
}
private bool ShouldDisplayCell(DataGridColumn column, double frozenLeftEdge, double scrollingLeftEdge)
{
if (!column.IsVisible)
{
return false;
}
Debug.Assert(OwningGrid != null);
scrollingLeftEdge += OwningGrid.HorizontalAdjustment;
double leftEdge = column.IsFrozen ? frozenLeftEdge : scrollingLeftEdge;
double rightEdge = leftEdge + column.ActualWidth;
return
MathUtilities.GreaterThan(rightEdge, 0) &&
MathUtilities.LessThanOrClose(leftEdge, OwningGrid.CellsWidth) &&
MathUtilities.GreaterThan(rightEdge, frozenLeftEdge); // scrolling column covered up by frozen column(s)
}
}
@@ -0,0 +1,57 @@
using System.Diagnostics;
using Avalonia.Controls;
namespace AtomUI.Controls;
public partial class DataGrid
{
#region 内部属性定义
// Width currently available for cells this value is smaller. This width is reduced by the existence of RowHeaders
// or a vertical scrollbar. Layout is asynchronous so changes to the RowHeaders or the vertical scrollbar are
// not reflected immediately
internal double CellsWidth
{
get
{
double rowsWidth = double.PositiveInfinity;
if (RowsPresenterAvailableSize.HasValue)
{
rowsWidth = Math.Max(0, RowsPresenterAvailableSize.Value.Width - ActualRowHeaderWidth);
}
return double.IsPositiveInfinity(rowsWidth) ? ColumnsInternal.VisibleEdgedColumnsWidth : rowsWidth;
}
}
internal int CurrentSlot
{
get => CurrentCellCoordinates.Slot;
private set => CurrentCellCoordinates.Slot = value;
}
internal int SlotCount { get; private set; }
internal double CellsEstimatedHeight => RowsPresenterAvailableSize?.Height ?? 0;
private bool IsHorizontalScrollBarOverCells => _columnHeadersPresenter != null && Grid.GetColumnSpan(_columnHeadersPresenter) == 2;
private bool IsVerticalScrollBarOverCells => _rowsPresenter != null && Grid.GetRowSpan(_rowsPresenter) == 2;
internal int VisibleSlotCount { get; set; }
internal double AvailableSlotElementRoom { get; set; }
#endregion
internal static DataGridCell? GetOwningCell(Control element)
{
Debug.Assert(element != null);
DataGridCell? cell = element as DataGridCell;
Control? target = element;
while (target != null && cell == null)
{
target = target.Parent as Control;
cell = target as DataGridCell;
}
return cell;
}
}
+7 -7
View File
@@ -1129,7 +1129,7 @@ public partial class DataGrid : TemplatedControl
/// <summary>
/// Raises the BeginningEdit event.
/// </summary>
protected virtual void OnBeginningEdit(DataGridBeginningEditEventArgs e)
protected virtual void NotifyBeginningEdit(DataGridBeginningEditEventArgs e)
{
BeginningEdit?.Invoke(this, e);
}
@@ -1137,7 +1137,7 @@ public partial class DataGrid : TemplatedControl
/// <summary>
/// Raises the CellEditEnded event.
/// </summary>
protected virtual void OnCellEditEnded(DataGridCellEditEndedEventArgs e)
protected virtual void NotifyCellEditEnded(DataGridCellEditEndedEventArgs e)
{
CellEditEnded?.Invoke(this, e);
}
@@ -1145,7 +1145,7 @@ public partial class DataGrid : TemplatedControl
/// <summary>
/// Raises the CellEditEnding event.
/// </summary>
protected virtual void OnCellEditEnding(DataGridCellEditEndingEventArgs e)
protected virtual void NotifyCellEditEnding(DataGridCellEditEndingEventArgs e)
{
CellEditEnding?.Invoke(this, e);
}
@@ -1153,7 +1153,7 @@ public partial class DataGrid : TemplatedControl
/// <summary>
/// Raises the CellPointerPressed event.
/// </summary>
internal virtual void OnCellPointerPressed(DataGridCellPointerPressedEventArgs e)
internal virtual void NotifyCellPointerPressed(DataGridCellPointerPressedEventArgs e)
{
CellPointerPressed?.Invoke(this, e);
}
@@ -2262,7 +2262,7 @@ public partial class DataGrid : TemplatedControl
// Raise the BeginningEdit event
DataGridCell dataGridCell = dataGridRow.Cells[CurrentColumnIndex];
DataGridBeginningEditEventArgs e = new DataGridBeginningEditEventArgs(CurrentColumn, dataGridRow, editingEventArgs);
OnBeginningEdit(e);
NotifyBeginningEdit(e);
if (e.Cancel
|| currentRowIndex != CurrentSlot
|| currentColumnIndex != CurrentColumnIndex
@@ -2951,7 +2951,7 @@ public partial class DataGrid : TemplatedControl
{
Debug.Assert(CurrentColumn != null);
DataGridCellEditEndingEventArgs e = new DataGridCellEditEndingEventArgs(CurrentColumn, editingRow, editingElement, editAction);
OnCellEditEnding(e);
NotifyCellEditEnding(e);
if (e.Cancel)
{
// CellEditEnding has been cancelled
@@ -3066,7 +3066,7 @@ public partial class DataGrid : TemplatedControl
// We're done, so raise the CellEditEnded event
if (raiseEvents)
{
OnCellEditEnded(new DataGridCellEditEndedEventArgs(CurrentColumn, editingRow, editAction));
NotifyCellEditEnded(new DataGridCellEditEndedEventArgs(CurrentColumn, editingRow, editAction));
}
// There's a chance that somebody reopened this cell for edit within the CellEditEnded handler,
@@ -5,7 +5,7 @@ namespace AtomUI.Controls;
internal class DataGridRowGroupInfo
{
public DataGridRowGroupInfo(
DataGridCollectionViewGroup collectionViewGroup,
DataGridCollectionViewGroup? collectionViewGroup,
bool isVisible,
int level,
int slot,
@@ -18,7 +18,7 @@ internal class DataGridRowGroupInfo
LastSubItemSlot = lastSubItemSlot;
}
public DataGridCollectionViewGroup CollectionViewGroup
public DataGridCollectionViewGroup? CollectionViewGroup
{
get;
private set;
@@ -6,6 +6,8 @@ namespace AtomUI.Controls;
[ControlThemeProvider]
internal class DataGridCellTheme : BaseControlTheme
{
public const string RightGridLinePart = "PART_RightGridLine";
public DataGridCellTheme()
: base(typeof(DataGridCell))
{