Browse Source

DataGrid: support hideable scrollbars and some another fixes

pull/4534/head
Maksym Katsydan 6 years ago
parent
commit
82bd2c487d
  1. 70
      src/Avalonia.Controls.DataGrid/DataGrid.cs
  2. 2
      src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
  3. 2
      src/Avalonia.Controls.DataGrid/DataGridRowHeader.cs
  4. 4
      src/Avalonia.Controls.DataGrid/Themes/Default.xaml
  5. 26
      src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml

70
src/Avalonia.Controls.DataGrid/DataGrid.cs

@ -39,6 +39,7 @@ namespace Avalonia.Controls
private const string DATAGRID_elementRowHeadersPresenterName = "PART_RowHeadersPresenter";
private const string DATAGRID_elementTopLeftCornerHeaderName = "PART_TopLeftCornerHeader";
private const string DATAGRID_elementTopRightCornerHeaderName = "PART_TopRightCornerHeader";
private const string DATAGRID_elementBottomRightCornerHeaderName = "PART_BottomRightCorner";
private const string DATAGRID_elementValidationSummary = "PART_ValidationSummary";
private const string DATAGRID_elementVerticalScrollbarName = "PART_VerticalScrollbar";
@ -79,6 +80,7 @@ namespace Avalonia.Controls
private INotifyCollectionChanged _topLevelGroup;
private ContentControl _clipboardContentControl;
private IVisual _bottomRightCorner;
private DataGridColumnHeadersPresenter _columnHeadersPresenter;
private DataGridRowsPresenter _rowsPresenter;
private ScrollBar _vScrollBar;
@ -1825,6 +1827,22 @@ namespace Avalonia.Controls
}
}
private bool IsHorizontalScrollBarOverCells
{
get
{
return _columnHeadersPresenter != null && Grid.GetColumnSpan(_columnHeadersPresenter) == 2;
}
}
private bool IsVerticalScrollBarOverCells
{
get
{
return _rowsPresenter != null && Grid.GetRowSpan(_rowsPresenter) == 2;
}
}
private int NoSelectionChangeCount
{
get
@ -2323,6 +2341,7 @@ namespace Avalonia.Controls
_topLeftCornerHeader = e.NameScope.Find<ContentControl>(DATAGRID_elementTopLeftCornerHeaderName);
EnsureTopLeftCornerHeader(); // EnsureTopLeftCornerHeader checks for a null _topLeftCornerHeader;
_topRightCornerHeader = e.NameScope.Find<ContentControl>(DATAGRID_elementTopRightCornerHeaderName);
_bottomRightCorner = e.NameScope.Find<IVisual>(DATAGRID_elementBottomRightCornerHeaderName);
}
/// <summary>
@ -3293,6 +3312,10 @@ namespace Avalonia.Controls
//
}
bool isHorizontalScrollBarOverCells = IsHorizontalScrollBarOverCells;
bool isVerticalScrollBarOverCells = IsVerticalScrollBarOverCells;
double cellsWidth = CellsWidth;
double cellsHeight = CellsHeight;
@ -3308,10 +3331,17 @@ namespace Avalonia.Controls
// Compensate if the horizontal scrollbar is already taking up space
if (!forceHorizScrollbar && _hScrollBar.IsVisible)
{
cellsHeight += _hScrollBar.DesiredSize.Height;
if (!isHorizontalScrollBarOverCells)
{
cellsHeight += _hScrollBar.DesiredSize.Height;
}
}
if (!isHorizontalScrollBarOverCells)
{
horizScrollBarHeight = _hScrollBar.Height + _hScrollBar.Margin.Top + _hScrollBar.Margin.Bottom;
}
horizScrollBarHeight = _hScrollBar.Height + _hScrollBar.Margin.Top + _hScrollBar.Margin.Bottom;
}
bool allowVertScrollbar = false;
bool forceVertScrollbar = false;
double vertScrollBarWidth = 0;
@ -3324,9 +3354,15 @@ namespace Avalonia.Controls
// Compensate if the vertical scrollbar is already taking up space
if (!forceVertScrollbar && _vScrollBar.IsVisible)
{
cellsWidth += _vScrollBar.DesiredSize.Width;
if (!isVerticalScrollBarOverCells)
{
cellsWidth += _vScrollBar.DesiredSize.Width;
}
}
if (!isVerticalScrollBarOverCells)
{
vertScrollBarWidth = _vScrollBar.Width + _vScrollBar.Margin.Left + _vScrollBar.Margin.Right;
}
vertScrollBarWidth = _vScrollBar.Width + _vScrollBar.Margin.Left + _vScrollBar.Margin.Right;
}
// Now cellsWidth is the width potentially available for displaying data cells.
@ -3354,7 +3390,9 @@ namespace Avalonia.Controls
cellsHeight -= horizScrollBarHeight;
Debug.Assert(cellsHeight >= 0);
needHorizScrollbarWithoutVertScrollbar = needHorizScrollbar = true;
if (allowVertScrollbar && (MathUtilities.LessThanOrClose(totalVisibleWidth - cellsWidth, vertScrollBarWidth) ||
if (vertScrollBarWidth > 0 &&
allowVertScrollbar && (MathUtilities.LessThanOrClose(totalVisibleWidth - cellsWidth, vertScrollBarWidth) ||
MathUtilities.LessThanOrClose(cellsWidth - totalVisibleFrozenWidth, vertScrollBarWidth)))
{
// Would we still need a horizontal scrollbar without the vertical one?
@ -3372,7 +3410,12 @@ namespace Avalonia.Controls
}
}
UpdateDisplayedRows(DisplayData.FirstScrollingSlot, cellsHeight);
// Store the current FirstScrollingSlot because removing the horizontal scrollbar could scroll
// the DataGrid up; however, if we realize later that we need to keep the horizontal scrollbar
// then we should use the first slot stored here which is not scrolled.
int firstScrollingSlot = DisplayData.FirstScrollingSlot;
UpdateDisplayedRows(firstScrollingSlot, cellsHeight);
if (allowVertScrollbar &&
MathUtilities.GreaterThan(cellsHeight, 0) &&
MathUtilities.LessThanOrClose(vertScrollBarWidth, cellsWidth) &&
@ -3384,10 +3427,12 @@ namespace Avalonia.Controls
}
DisplayData.FirstDisplayedScrollingCol = ComputeFirstVisibleScrollingColumn();
// we compute the number of visible columns only after we set up the vertical scroll bar.
ComputeDisplayedColumns();
if (allowHorizScrollbar &&
if ((vertScrollBarWidth > 0 || horizScrollBarHeight > 0) &&
allowHorizScrollbar &&
needVertScrollbar && !needHorizScrollbar &&
MathUtilities.GreaterThan(totalVisibleWidth, cellsWidth) &&
MathUtilities.LessThan(totalVisibleFrozenWidth, cellsWidth) &&
@ -3398,7 +3443,7 @@ namespace Avalonia.Controls
Debug.Assert(cellsHeight >= 0);
needVertScrollbar = false;
UpdateDisplayedRows(DisplayData.FirstScrollingSlot, cellsHeight);
UpdateDisplayedRows(firstScrollingSlot, cellsHeight);
if (cellsHeight > 0 &&
vertScrollBarWidth <= cellsWidth &&
DisplayData.NumTotallyDisplayedScrollingElements != VisibleSlotCount)
@ -3479,6 +3524,15 @@ namespace Avalonia.Controls
_topRightCornerHeader.IsVisible = false;
}
}
if (_bottomRightCorner != null)
{
// Show the BottomRightCorner when both scrollbars are visible.
_bottomRightCorner.IsVisible =
_hScrollBar != null && _hScrollBar.IsVisible &&
_vScrollBar != null && _vScrollBar.IsVisible;
}
DisplayData.FullyRecycleElements();
}

2
src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs

@ -40,7 +40,7 @@ namespace Avalonia.Controls
private static Cursor _originalCursor;
private static double _originalHorizontalOffset;
private static double _originalWidth;
private bool _desiredSeparatorVisibility;
private bool _desiredSeparatorVisibility = true;
private static Point? _dragStart;
private static DataGridColumn _dragColumn;
private static double _frozenColumnsWidth;

2
src/Avalonia.Controls.DataGrid/DataGridRowHeader.cs

@ -14,7 +14,7 @@ namespace Avalonia.Controls.Primitives
/// </summary>
public class DataGridRowHeader : ContentControl
{
private const string DATAGRIDROWHEADER_elementRootName = "Root";
private const string DATAGRIDROWHEADER_elementRootName = "PART_Root";
private const double DATAGRIDROWHEADER_separatorThickness = 1;
private Control _rootElement;

4
src/Avalonia.Controls.DataGrid/Themes/Default.xaml

@ -139,7 +139,7 @@
<Style Selector="DataGridRowHeader">
<Setter Property="Template">
<ControlTemplate>
<Grid
<Grid x:Name="PART_Root"
RowDefinitions="*,*,Auto"
ColumnDefinitions="Auto,*">
@ -224,7 +224,7 @@
<Rectangle Name="PART_ColumnHeadersAndRowsSeparator" Grid.ColumnSpan="3" VerticalAlignment="Bottom" StrokeThickness="1" Height="1" Fill="{DynamicResource ThemeControlMidHighBrush}"/>
<DataGridRowsPresenter Name="PART_RowsPresenter" Grid.ColumnSpan="2" Grid.Row="1" />
<Rectangle Name="BottomRightCorner" Fill="{DynamicResource ThemeControlMidHighBrush}" Grid.Column="2" Grid.Row="2" />
<Rectangle Name="PART_BottomRightCorner" Fill="{DynamicResource ThemeControlMidHighBrush}" Grid.Column="2" Grid.Row="2" />
<Rectangle Name="BottomLeftCorner" Fill="{DynamicResource ThemeControlMidHighBrush}" Grid.Row="2" Grid.ColumnSpan="2" />
<ScrollBar Name="PART_VerticalScrollbar" Orientation="Vertical" Grid.Column="2" Grid.Row="1" Width="{DynamicResource ScrollBarThickness}"/>

26
src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml

@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Styles.Resources>
<Thickness x:Key="DataGridTextColumnCellTextBlockMargin">12,0,12,0</Thickness>
<SolidColorBrush x:Key="DropLocationIndicatorBackground"
Color="#3F4346" />
<SolidColorBrush x:Key="DisabledVisualElementBackground"
@ -88,7 +88,7 @@
<StaticResource x:Key="DataGridRowGroupHeaderForegroundBrush"
ResourceKey="SystemControlForegroundBaseHighBrush" />
<StaticResource x:Key="DataGridRowInvalidBrush"
ResourceKey="SystemControlErrorTextForegroundBrush" />
ResourceKey="SystemErrorTextColor" />
<StaticResource x:Key="DataGridCellBackgroundBrush"
ResourceKey="SystemControlTransparentBrush" />
<StaticResource x:Key="DataGridCellFocusVisualPrimaryBrush"
@ -96,7 +96,7 @@
<StaticResource x:Key="DataGridCellFocusVisualSecondaryBrush"
ResourceKey="SystemControlFocusVisualSecondaryBrush" />
<StaticResource x:Key="DataGridCellInvalidBrush"
ResourceKey="SystemControlErrorTextForegroundBrush" />
ResourceKey="SystemErrorTextColor" />
</Styles.Resources>
<Style Selector="DataGridCell">
@ -356,7 +356,7 @@
<Setter Property="AreSeparatorsVisible" Value="False" />
<Setter Property="Template">
<ControlTemplate>
<Grid x:Name="PART_RowHeaderRoot"
<Grid x:Name="PART_Root"
RowDefinitions="*,*,Auto"
ColumnDefinitions="Auto,*">
<Border Grid.RowSpan="3"
@ -403,14 +403,14 @@
<Style Selector="DataGridRowHeader /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource SystemControlTransparentBrush}" />
</Style>
<Style Selector="DataGridRowHeader:pointerover /template/ Rectangle#BackgroundRectangle">
<Style Selector="DataGridRow:pointerover DataGridRowHeader /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource SystemListLowColor}" />
</Style>
<Style Selector="DataGridRowHeader:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource DataGridRowSelectedUnfocusedBackgroundColor}" />
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedUnfocusedBackgroundOpacity}" />
</Style>
<Style Selector="DataGridRowHeader:selected:pointerover /template/ Rectangle#BackgroundRectangle">
<Style Selector="DataGridRow:pointerover DataGridRowHeader:selected /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource DataGridRowSelectedHoveredUnfocusedBackgroundColor}" />
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedHoveredUnfocusedBackgroundOpacity}" />
</Style>
@ -418,7 +418,7 @@
<Setter Property="Fill" Value="{DynamicResource DataGridRowSelectedBackgroundColor}" />
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedBackgroundOpacity}" />
</Style>
<Style Selector="DataGridRowHeader:selected:pointerover:focus /template/ Rectangle#BackgroundRectangle">
<Style Selector="DataGridRow:pointerover DataGridRowHeader:selected:focus /template/ Rectangle#BackgroundRectangle">
<Setter Property="Fill" Value="{DynamicResource DataGridRowSelectedHoveredBackgroundColor}" />
<Setter Property="Opacity" Value="{DynamicResource DataGridRowSelectedHoveredBackgroundOpacity}" />
</Style>
@ -606,18 +606,24 @@
<!--<DataGridColumnHeader Name="PART_TopRightCornerHeader"
Grid.Column="2"
Template="{StaticResource TopRightHeaderTemplate}" />-->
<Rectangle Name="PART_ColumnHeadersAndRowsSeparator"
<!--<Rectangle Name="PART_ColumnHeadersAndRowsSeparator"
Grid.ColumnSpan="3"
VerticalAlignment="Bottom"
StrokeThickness="1"
Height="1"
Fill="{DynamicResource GridLinesBrush}" />
Fill="{DynamicResource GridLinesBrush}" />-->
<Border Name="PART_ColumnHeadersAndRowsSeparator"
Grid.ColumnSpan="3"
Height="2"
VerticalAlignment="Bottom"
BorderThickness="0,0,0,1"
BorderBrush="{DynamicResource GridLinesBrush}" />
<DataGridRowsPresenter Name="PART_RowsPresenter"
Grid.Row="1"
Grid.RowSpan="2"
Grid.ColumnSpan="3" />
<Rectangle Name="BottomRightCorner"
<Rectangle Name="PART_BottomRightCorner"
Fill="{DynamicResource ScrollBarsSeparatorBackground}"
Grid.Column="2"
Grid.Row="2" />

Loading…
Cancel
Save