Browse Source

Merge pull request #11289 from AvaloniaUI/datagrid-fix

DataGrid fixes
release/11.0.0-preview8
Max Katz 3 years ago
committed by GitHub
parent
commit
b3bca1ae76
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      dirs.proj
  2. 39
      src/Avalonia.Controls.DataGrid/DataGrid.cs
  3. 8
      src/Avalonia.Controls.DataGrid/DataGridCell.cs
  4. 1
      src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs
  5. 14
      src/Avalonia.Controls.DataGrid/DataGridColumns.cs
  6. 1
      src/Avalonia.Controls.DataGrid/DataGridRow.cs
  7. 4
      src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs
  8. 17
      src/Avalonia.Controls.DataGrid/DataGridRows.cs
  9. 8
      src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
  10. 1
      src/Avalonia.Controls.DataGrid/Themes/Simple.xaml
  11. 2
      src/Avalonia.Controls.DataGrid/Utils/TreeHelper.cs
  12. 4
      src/Avalonia.Controls/Control.cs

5
dirs.proj

@ -9,10 +9,11 @@
<ProjectReference Remove="**/*.shproj" />
<ProjectReference Remove="src/Markup/Avalonia.Markup.Xaml/PortableXaml/**/*.*proj" />
<ProjectReference Remove="src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github/**/*.*proj" />
<!-- Exclude iOS, Android and Web samples from build -->
<!-- Exclude iOS, Android and Browser samples from build -->
<ProjectReference Remove="samples/*.iOS/*.csproj" />
<ProjectReference Remove="samples/*.Android/*.csproj" />
<ProjectReference Remove="samples/*.Web/*.csproj" />
<ProjectReference Remove="samples/*.Browser/*.csproj" />
<ProjectReference Remove="samples/*.Blazor/*.csproj" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows')) OR '$(MSBuildRuntimeType)' != 'Full'">
<ProjectReference Remove="src/Windows/Avalonia.Win32.Interop/Avalonia.Win32.Interop.csproj" />

39
src/Avalonia.Controls.DataGrid/DataGrid.cs

@ -729,6 +729,8 @@ namespace Avalonia.Controls
RowDetailsTemplateProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnRowDetailsTemplateChanged(e));
RowDetailsVisibilityModeProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnRowDetailsVisibilityModeChanged(e));
AutoGenerateColumnsProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnAutoGenerateColumnsChanged(e));
FocusableProperty.OverrideDefaultValue<DataGrid>(true);
}
/// <summary>
@ -2478,7 +2480,7 @@ namespace Avalonia.Controls
if (_hScrollBar != null)
{
//_hScrollBar.IsTabStop = false;
_hScrollBar.IsTabStop = false;
_hScrollBar.Maximum = 0.0;
_hScrollBar.Orientation = Orientation.Horizontal;
_hScrollBar.IsVisible = false;
@ -2494,7 +2496,7 @@ namespace Avalonia.Controls
if (_vScrollBar != null)
{
//_vScrollBar.IsTabStop = false;
_vScrollBar.IsTabStop = false;
_vScrollBar.Maximum = 0.0;
_vScrollBar.Orientation = Orientation.Vertical;
_vScrollBar.IsVisible = false;
@ -3734,7 +3736,7 @@ namespace Avalonia.Controls
if (sender is Control editingElement)
{
editingElement.LostFocus -= EditingElement_LostFocus;
if (EditingRow != null && EditingColumnIndex != -1)
if (EditingRow != null && _editingColumnIndex != -1)
{
FocusEditingCell(true);
}
@ -4039,18 +4041,22 @@ namespace Avalonia.Controls
return true;
}
Debug.Assert(EditingRow != null);
var editingRow = EditingRow;
if (editingRow is null)
{
return true;
}
Debug.Assert(_editingColumnIndex >= 0);
Debug.Assert(_editingColumnIndex < ColumnsItemsInternal.Count);
Debug.Assert(_editingColumnIndex == CurrentColumnIndex);
Debug.Assert(EditingRow != null && EditingRow.Slot == CurrentSlot);
// Cache these to see if they change later
int currentSlot = CurrentSlot;
int currentColumnIndex = CurrentColumnIndex;
// We're ready to start ending, so raise the event
DataGridCell editingCell = EditingRow.Cells[_editingColumnIndex];
DataGridCell editingCell = editingRow.Cells[_editingColumnIndex];
var editingElement = editingCell.Content as Control;
if (editingElement == null)
{
@ -4058,7 +4064,7 @@ namespace Avalonia.Controls
}
if (raiseEvents)
{
DataGridCellEditEndingEventArgs e = new DataGridCellEditEndingEventArgs(CurrentColumn, EditingRow, editingElement, editAction);
DataGridCellEditEndingEventArgs e = new DataGridCellEditEndingEventArgs(CurrentColumn, editingRow, editingElement, editAction);
OnCellEditEnding(e);
if (e.Cancel)
{
@ -4112,7 +4118,7 @@ namespace Avalonia.Controls
}
else
{
if (EditingRow != null)
if (editingRow != null)
{
if (editingCell.IsValid)
{
@ -4120,10 +4126,10 @@ namespace Avalonia.Controls
editingCell.UpdatePseudoClasses();
}
if (EditingRow.IsValid)
if (editingRow.IsValid)
{
EditingRow.IsValid = false;
EditingRow.UpdatePseudoClasses();
editingRow.IsValid = false;
editingRow.UpdatePseudoClasses();
}
}
@ -4169,22 +4175,22 @@ namespace Avalonia.Controls
PopulateCellContent(
isCellEdited: !exitEditingMode,
dataGridColumn: CurrentColumn,
dataGridRow: EditingRow,
dataGridRow: editingRow,
dataGridCell: editingCell);
EditingRow.InvalidateDesiredHeight();
editingRow.InvalidateDesiredHeight();
var column = editingCell.OwningColumn;
if (column.Width.IsSizeToCells || column.Width.IsAuto)
{// Invalidate desired width and force recalculation
column.SetWidthDesiredValue(0);
EditingRow.OwningGrid.AutoSizeColumn(column, editingCell.DesiredSize.Width);
editingRow.OwningGrid.AutoSizeColumn(column, editingCell.DesiredSize.Width);
}
}
// We're done, so raise the CellEditEnded event
if (raiseEvents)
{
OnCellEditEnded(new DataGridCellEditEndedEventArgs(CurrentColumn, EditingRow, editAction));
OnCellEditEnded(new DataGridCellEditEndedEventArgs(CurrentColumn, editingRow, editAction));
}
// There's a chance that somebody reopened this cell for edit within the CellEditEnded handler,
@ -4427,8 +4433,7 @@ namespace Avalonia.Controls
dataGridCell.Focus();
success = dataGridCell.ContainsFocusedElement();
}
//TODO Check
//success = dataGridCell.ContainsFocusedElement() ? true : dataGridCell.Focus();
_focusEditingControl = !success;
}
return success;

8
src/Avalonia.Controls.DataGrid/DataGridCell.cs

@ -33,6 +33,8 @@ namespace Avalonia.Controls
{
PointerPressedEvent.AddClassHandler<DataGridCell>(
(x,e) => x.DataGridCell_PointerPressed(e), handledEventsToo: true);
FocusableProperty.OverrideDefaultValue<DataGridCell>(true);
IsTabStopProperty.OverrideDefaultValue<DataGridCell>(false);
}
public DataGridCell()
{ }
@ -169,8 +171,7 @@ namespace Avalonia.Controls
OwningGrid.OnCellPointerPressed(new DataGridCellPointerPressedEventArgs(this, OwningRow, OwningColumn, e));
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
{
if (!e.Handled)
//if (!e.Handled && OwningGrid.IsTabStop)
if (!e.Handled && OwningGrid.IsTabStop)
{
OwningGrid.Focus();
}
@ -190,8 +191,7 @@ namespace Avalonia.Controls
}
else if (e.GetCurrentPoint(this).Properties.IsRightButtonPressed)
{
if (!e.Handled)
//if (!e.Handled && OwningGrid.IsTabStop)
if (!e.Handled && OwningGrid.IsTabStop)
{
OwningGrid.Focus();
}

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

@ -72,6 +72,7 @@ namespace Avalonia.Controls
{
AreSeparatorsVisibleProperty.Changed.AddClassHandler<DataGridColumnHeader>((x, e) => x.OnAreSeparatorsVisibleChanged(e));
PressedMixin.Attach<DataGridColumnHeader>();
IsTabStopProperty.OverrideDefaultValue<DataGridColumnHeader>(false);
}
/// <summary>

14
src/Avalonia.Controls.DataGrid/DataGridColumns.cs

@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Reflection;
using Avalonia.Layout;
namespace Avalonia.Controls
{
@ -489,7 +490,7 @@ namespace Avalonia.Controls
{
DataGridFillerColumn fillerColumn = ColumnsInternal.FillerColumn;
double totalColumnsWidth = ColumnsInternal.VisibleEdgedColumnsWidth;
if (finalWidth > totalColumnsWidth)
if (finalWidth - totalColumnsWidth > LayoutHelper.LayoutEpsilon)
{
fillerColumn.FillerWidth = finalWidth - totalColumnsWidth;
}
@ -971,6 +972,12 @@ namespace Avalonia.Controls
{
cx += _negHorizontalOffset;
_horizontalOffset -= _negHorizontalOffset;
if (_horizontalOffset < LayoutHelper.LayoutEpsilon)
{
// Snap to zero to avoid trying to partially scroll in first scrolled off column below
_horizontalOffset = 0;
}
_negHorizontalOffset = 0;
}
else
@ -979,6 +986,11 @@ namespace Avalonia.Controls
_negHorizontalOffset -= displayWidth - cx;
cx = displayWidth;
}
// Make sure the HorizontalAdjustment is not greater than the new HorizontalOffset
// since it would cause an assertion failure in DataGridCellsPresenter.ShouldDisplayCell
// called by DataGridCellsPresenter.MeasureOverride.
HorizontalAdjustment = Math.Min(HorizontalAdjustment, _horizontalOffset);
}
// second try to scroll entire columns
if (cx < displayWidth && _horizontalOffset > 0)

1
src/Avalonia.Controls.DataGrid/DataGridRow.cs

@ -128,6 +128,7 @@ namespace Avalonia.Controls
DetailsTemplateProperty.Changed.AddClassHandler<DataGridRow>((x, e) => x.OnDetailsTemplateChanged(e));
AreDetailsVisibleProperty.Changed.AddClassHandler<DataGridRow>((x, e) => x.OnAreDetailsVisibleChanged(e));
PointerPressedEvent.AddClassHandler<DataGridRow>((x, e) => x.DataGridRow_PointerPressed(e), handledEventsToo: true);
IsTabStopProperty.OverrideDefaultValue<DataGridRow>(false);
}
/// <summary>

4
src/Avalonia.Controls.DataGrid/DataGridRowGroupHeader.cs

@ -106,6 +106,7 @@ namespace Avalonia.Controls
{
SublevelIndentProperty.Changed.AddClassHandler<DataGridRowGroupHeader>((x,e) => x.OnSublevelIndentChanged(e));
PressedMixin.Attach<DataGridRowGroupHeader>();
IsTabStopProperty.OverrideDefaultValue<DataGridRowGroupHeader>(false);
}
/// <summary>
@ -301,8 +302,7 @@ namespace Avalonia.Controls
}
else
{
//if (!e.Handled && OwningGrid.IsTabStop)
if (!e.Handled)
if (!e.Handled && OwningGrid.IsTabStop)
{
OwningGrid.Focus();
}

17
src/Avalonia.Controls.DataGrid/DataGridRows.cs

@ -1589,6 +1589,23 @@ namespace Avalonia.Controls
CorrectSlotsAfterDeletion(slot, isRow);
OnRemovedElement(slot, item);
// Synchronize CurrentCellCoordinates, CurrentColumn, CurrentColumnIndex, CurrentItem
// and CurrentSlot with the currently edited cell, since OnRemovingElement called
// SetCurrentCellCore(-1, -1) to temporarily reset the current cell.
if (_temporarilyResetCurrentCell &&
_editingColumnIndex != -1 &&
_previousCurrentItem != null &&
EditingRow != null &&
EditingRow.Slot != -1)
{
ProcessSelectionAndCurrency(
columnIndex: _editingColumnIndex,
item: _previousCurrentItem,
backupSlot: this.EditingRow.Slot,
action: DataGridSelectionAction.None,
scrollIntoView: false);
}
}
private void RemoveNonDisplayedRows(int newFirstDisplayedSlot, int newLastDisplayedSlot)

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

@ -82,7 +82,6 @@
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="FontSize" Value="15" />
<Setter Property="MinHeight" Value="32" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<ControlTemplate>
<Border x:Name="CellBorder"
@ -157,7 +156,6 @@
<Setter Property="Background" Value="{DynamicResource DataGridColumnHeaderBackgroundBrush}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Focusable" Value="False" />
<Setter Property="SeparatorBrush" Value="{DynamicResource DataGridGridLinesBrush}" />
<Setter Property="Padding" Value="12,0,0,0" />
<Setter Property="FontSize" Value="12" />
@ -268,7 +266,6 @@
</ControlTheme>
<ControlTheme x:Key="{x:Type DataGridRowHeader}" TargetType="DataGridRowHeader">
<Setter Property="Focusable" Value="False" />
<Setter Property="SeparatorBrush" Value="{DynamicResource DataGridGridLinesBrush}" />
<Setter Property="AreSeparatorsVisible" Value="False" />
<Setter Property="Template">
@ -310,7 +307,6 @@
</ControlTheme>
<ControlTheme x:Key="{x:Type DataGridRow}" TargetType="DataGridRow">
<Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="{Binding $parent[DataGrid].RowBackground}" />
<Setter Property="Template">
<ControlTemplate>
@ -408,7 +404,6 @@
</ControlTheme>
<ControlTheme x:Key="{x:Type DataGridRowGroupHeader}" TargetType="DataGridRowGroupHeader">
<Setter Property="Focusable" Value="False" />
<Setter Property="Foreground" Value="{DynamicResource DataGridRowGroupHeaderForegroundBrush}" />
<Setter Property="Background" Value="{DynamicResource DataGridRowGroupHeaderBackgroundBrush}" />
<Setter Property="FontSize" Value="15" />
@ -433,7 +428,7 @@
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="{TemplateBinding CornerRadius}"
Focusable="False"
IsTabStop="False"
Foreground="{TemplateBinding Foreground}" />
<StackPanel Grid.Column="3"
@ -503,6 +498,7 @@
<Setter Property="GridLinesVisibility" Value="None" />
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource DataGridGridLinesBrush}" />
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource DataGridGridLinesBrush}" />
<Setter Property="FocusAdorner" Value="{x:Null}" />
<Setter Property="DropLocationIndicatorTemplate">
<Template>
<Rectangle Fill="{DynamicResource DataGridDropLocationIndicatorBackground}"

1
src/Avalonia.Controls.DataGrid/Themes/Simple.xaml

@ -126,7 +126,6 @@
<ControlTheme x:Key="{x:Type DataGridRowHeader}"
TargetType="DataGridRowHeader">
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<ControlTemplate>
<Grid x:Name="PART_Root"

2
src/Avalonia.Controls.DataGrid/Utils/TreeHelper.cs

@ -54,7 +54,7 @@ namespace Avalonia.Controls.Utils
/// <returns>True if the currently focused element is within the visual tree of the parent</returns>
internal static bool ContainsFocusedElement(this Visual element)
{
return (element == null) ? false : element.ContainsChild(FocusManager.Instance.Current as Visual);
return element is InputElement { IsKeyboardFocusWithin: true };
}
}
}

4
src/Avalonia.Controls/Control.cs

@ -403,7 +403,9 @@ namespace Avalonia.Controls
{
if (_focusAdorner == null)
{
var template = GetValue(FocusAdornerProperty) ?? adornerLayer.DefaultFocusAdorner;
var template = IsSet(FocusAdornerProperty)
? GetValue(FocusAdornerProperty)
: adornerLayer.DefaultFocusAdorner;
if (template != null)
{

Loading…
Cancel
Save