Browse Source

Merge branch 'master' into findresource-bench

pull/7971/head
Steven Kirk 4 years ago
committed by GitHub
parent
commit
653d9c0e35
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      samples/ControlCatalog/Pages/DataGridPage.xaml
  2. 4
      src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs
  3. 10
      src/Avalonia.Controls.DataGrid/DataGrid.cs
  4. 2
      src/Avalonia.Controls.DataGrid/DataGridColumn.cs
  5. 36
      src/Avalonia.Controls.DataGrid/DataGridColumnCollection.cs
  6. 9
      src/Avalonia.Controls.DataGrid/DataGridColumns.cs
  7. 36
      src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs
  8. 39
      src/Avalonia.Controls.DataGrid/DataGridRow.cs
  9. 7
      src/Avalonia.Controls.DataGrid/DataGridRows.cs
  10. 5
      src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs
  11. 39
      src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs
  12. 36
      src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs
  13. 29
      src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs
  14. 145
      src/Avalonia.Controls.DataGrid/Themes/Default.xaml
  15. 264
      src/Avalonia.Controls.DataGrid/Themes/Fluent.xaml
  16. 5
      src/Avalonia.Controls/Calendar/DateTimeHelper.cs
  17. 2
      src/Avalonia.Controls/ItemsControl.cs
  18. 2
      src/Avalonia.Controls/Panel.cs
  19. 2
      src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs

19
samples/ControlCatalog/Pages/DataGridPage.xaml

@ -13,9 +13,22 @@
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="DataGridCell.gdp">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Background" Value="{Binding Path=GDP, Mode=OneWay, Converter={StaticResource GDPConverter}}" />
</Style>
<Style Selector="DataGridColumnHeader:nth-last-child(1)">
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style Selector="DataGridCell:nth-last-child(1)">
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style Selector="DataGrid#dataGridGrouping DataGridRow:nth-child(5n+3)">
<Setter Property="Foreground" Value="Red" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style Selector="DataGrid#dataGridGrouping DataGridRow:nth-last-child(5n+1)">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</UserControl.Styles>
<Grid RowDefinitions="Auto,Auto,*">
<StackPanel Orientation="Vertical" Spacing="4" Grid.Row="0">
@ -31,7 +44,9 @@
<DockPanel>
<CheckBox x:Name="ShowGDP" IsChecked="True" Content="Toggle GDP Column Visibility"
DockPanel.Dock="Top"/>
<DataGrid Name="dataGrid1" Margin="12" CanUserResizeColumns="True" CanUserReorderColumns="True" CanUserSortColumns="True" HeadersVisibility="All">
<DataGrid Name="dataGrid1" Margin="12" CanUserResizeColumns="True" CanUserReorderColumns="True" CanUserSortColumns="True" HeadersVisibility="All"
RowBackground="#1000"
AlternatingRowBackground="#1fff">
<DataGrid.Columns>
<!-- Using HeaderTemplate -->
<DataGridTextColumn Header="Country" HeaderTemplate="{StaticResource Demo.DataTemplates.CountryHeader}" Binding="{Binding Name}" Width="6*" />

4
src/Avalonia.Base/LogicalTree/ChildIndexChangedEventArgs.cs

@ -8,7 +8,9 @@ namespace Avalonia.LogicalTree
/// </summary>
public class ChildIndexChangedEventArgs : EventArgs
{
public ChildIndexChangedEventArgs()
public static new ChildIndexChangedEventArgs Empty { get; } = new ChildIndexChangedEventArgs();
private ChildIndexChangedEventArgs()
{
}

10
src/Avalonia.Controls.DataGrid/DataGrid.cs

@ -669,8 +669,6 @@ namespace Avalonia.Controls
ItemsProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnItemsPropertyChanged(e));
CanUserResizeColumnsProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnCanUserResizeColumnsChanged(e));
ColumnWidthProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnColumnWidthChanged(e));
RowBackgroundProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnRowBackgroundChanged(e));
AlternatingRowBackgroundProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnRowBackgroundChanged(e));
FrozenColumnCountProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnFrozenColumnCountChanged(e));
GridLinesVisibilityProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnGridLinesVisibilityChanged(e));
HeadersVisibilityProperty.Changed.AddClassHandler<DataGrid>((x, e) => x.OnHeadersVisibilityChanged(e));
@ -1144,14 +1142,6 @@ namespace Avalonia.Controls
InvalidateCellsArrange();
}
private void OnRowBackgroundChanged(AvaloniaPropertyChangedEventArgs e)
{
foreach (DataGridRow row in GetAllRows())
{
row.EnsureBackground();
}
}
private void OnColumnWidthChanged(AvaloniaPropertyChangedEventArgs e)
{
var value = (DataGridLength)e.NewValue;

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

@ -199,7 +199,7 @@ namespace Avalonia.Controls
if (change.Property == IsVisibleProperty)
{
OwningGrid?.OnColumnVisibleStateChanging(this);
var isVisible = (change as AvaloniaPropertyChangedEventArgs<bool>).NewValue.Value;
var isVisible = change.NewValue.GetValueOrDefault<bool>();
if (_headerCell != null)
{

36
src/Avalonia.Controls.DataGrid/DataGridColumnCollection.cs

@ -12,7 +12,8 @@ namespace Avalonia.Controls
{
internal class DataGridColumnCollection : ObservableCollection<DataGridColumn>
{
private DataGrid _owningGrid;
private readonly Dictionary<int, int> _columnsMap = new Dictionary<int, int>();
private readonly DataGrid _owningGrid;
public DataGridColumnCollection(DataGrid owningGrid)
{
@ -124,18 +125,8 @@ namespace Avalonia.Controls
internal int VisibleColumnCount
{
get
{
int visibleColumnCount = 0;
for (int columnIndex = 0; columnIndex < ItemsInternal.Count; columnIndex++)
{
if (ItemsInternal[columnIndex].IsVisible)
{
visibleColumnCount++;
}
}
return visibleColumnCount;
}
get;
private set;
}
internal double VisibleEdgedColumnsWidth
@ -287,20 +278,31 @@ namespace Avalonia.Controls
{
VisibleStarColumnCount = 0;
VisibleEdgedColumnsWidth = 0;
VisibleColumnCount = 0;
_columnsMap.Clear();
for (int columnIndex = 0; columnIndex < ItemsInternal.Count; columnIndex++)
{
if (ItemsInternal[columnIndex].IsVisible)
var item = ItemsInternal[columnIndex];
_columnsMap[columnIndex] = item.DisplayIndex;
if (item.IsVisible)
{
ItemsInternal[columnIndex].EnsureWidth();
if (ItemsInternal[columnIndex].Width.IsStar)
VisibleColumnCount++;
item.EnsureWidth();
if (item.Width.IsStar)
{
VisibleStarColumnCount++;
}
VisibleEdgedColumnsWidth += ItemsInternal[columnIndex].ActualWidth;
VisibleEdgedColumnsWidth += item.ActualWidth;
}
}
}
internal int GetColumnDisplayIndex(int columnIndex)
{
return _columnsMap.TryGetValue(columnIndex, out var displayIndex) ? displayIndex : -1;
}
internal DataGridColumn GetColumnAtDisplayIndex(int displayIndex)
{
if (displayIndex < 0 || displayIndex >= ItemsInternal.Count || displayIndex >= DisplayIndexMap.Count)

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

@ -444,12 +444,11 @@ namespace Avalonia.Controls
// We need to explicitly collapse the cells of the invisible column because layout only goes through
// visible ones
if (!updatedColumn.IsVisible)
ColumnHeaders?.InvalidateChildIndex();
foreach (var row in GetAllRows())
{
foreach (DataGridRow row in GetAllRows())
{
row.Cells[updatedColumn.Index].IsVisible = false;
}
row.Cells[updatedColumn.Index].IsVisible = updatedColumn.IsVisible;
row.InvalidateCellsIndex();
}
}

36
src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs

@ -77,7 +77,7 @@ namespace Avalonia.Controls
private set;
}
public int Count => GetCount(true);
public int Count => TryGetCount(true, false, out var count) ? count : 0;
public bool DataIsPrimitive
{
@ -193,22 +193,25 @@ namespace Avalonia.Controls
}
}
internal bool Any()
{
return GetCount(false) > 0;
}
/// <param name="allowSlow">When "allowSlow" is false, method will not use Linq.Count() method and will return 0 or 1 instead.</param>
private int GetCount(bool allowSlow)
/// <param name="getAny">If "getAny" is true, method can use Linq.Any() method to speedup.</param>
internal bool TryGetCount(bool allowSlow, bool getAny, out int count)
{
return DataSource switch
bool result;
(result, count) = DataSource switch
{
ICollection collection => collection.Count,
DataGridCollectionView cv => cv.Count,
IEnumerable enumerable when allowSlow => enumerable.Cast<object>().Count(),
IEnumerable enumerable when !allowSlow => enumerable.Cast<object>().Any() ? 1 : 0,
_ => 0
ICollection collection => (true, collection.Count),
DataGridCollectionView cv => (true, cv.Count),
IEnumerable enumerable when allowSlow && !getAny => (true, enumerable.Cast<object>().Count()),
IEnumerable enumerable when getAny => (true, enumerable.Cast<object>().Any() ? 1 : 0),
_ => (false, 0)
};
return result;
}
internal bool Any()
{
return TryGetCount(false, true, out var count) && count > 0;
}
/// <summary>
@ -383,7 +386,7 @@ namespace Avalonia.Controls
List<string> propertyNames = TypeHelper.SplitPropertyPath(propertyName);
for (int i = 0; i < propertyNames.Count; i++)
{
propertyInfo = propertyType.GetPropertyOrIndexer(propertyNames[i], out object[] index);
propertyInfo = propertyType.GetPropertyOrIndexer(propertyNames[i], out _);
if (propertyInfo == null || propertyType.GetIsReadOnly() || propertyInfo.GetIsReadOnly())
{
// Either the data type is read-only, the property doesn't exist, or it does exist but is read-only
@ -391,11 +394,10 @@ namespace Avalonia.Controls
}
// Check if EditableAttribute is defined on the property and if it indicates uneditable
object[] attributes = propertyInfo.GetCustomAttributes(typeof(EditableAttribute), true);
var attributes = propertyInfo.GetCustomAttributes(typeof(EditableAttribute), true);
if (attributes != null && attributes.Length > 0)
{
EditableAttribute editableAttribute = attributes[0] as EditableAttribute;
Debug.Assert(editableAttribute != null);
var editableAttribute = (EditableAttribute)attributes[0];
if (!editableAttribute.AllowEdit)
{
return true;

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

@ -543,7 +543,6 @@ namespace Avalonia.Controls
RootElement = e.NameScope.Find<Panel>(DATAGRIDROW_elementRoot);
if (RootElement != null)
{
EnsureBackground();
UpdatePseudoClasses();
}
@ -668,43 +667,9 @@ namespace Avalonia.Controls
Slot = -1;
}
// Make sure the row's background is set to its correct value. It could be explicity set or inherit
// DataGrid.RowBackground or DataGrid.AlternatingRowBackground
internal void EnsureBackground()
internal void InvalidateCellsIndex()
{
// Inherit the DataGrid's RowBackground properties only if this row doesn't explicity have a background set
if (RootElement != null && OwningGrid != null)
{
IBrush newBackground = null;
if (Background == null)
{
if (Index % 2 == 0 || OwningGrid.AlternatingRowBackground == null)
{
// Use OwningGrid.RowBackground if the index is even or if the OwningGrid.AlternatingRowBackground is null
if (OwningGrid.RowBackground != null)
{
newBackground = OwningGrid.RowBackground;
}
}
else
{
// Alternate row
if (OwningGrid.AlternatingRowBackground != null)
{
newBackground = OwningGrid.AlternatingRowBackground;
}
}
}
else
{
newBackground = Background;
}
if (RootElement.Background != newBackground)
{
RootElement.Background = newBackground;
}
}
_cellsElement?.InvalidateChildIndex();
}
internal void EnsureFillerVisibility()

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

@ -5,6 +5,7 @@
using Avalonia.Collections;
using Avalonia.Controls.Utils;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Utilities;
using System;
@ -811,7 +812,7 @@ namespace Avalonia.Controls
if (row.Slot > slotDeleted)
{
CorrectRowAfterDeletion(row, wasRow);
row.EnsureBackground();
_rowsPresenter?.InvalidateChildIndex(row);
}
}
@ -867,7 +868,7 @@ namespace Avalonia.Controls
if (row.Slot >= slotInserted)
{
DataGrid.CorrectRowAfterInsertion(row, rowInserted);
row.EnsureBackground();
_rowsPresenter?.InvalidateChildIndex(row);
}
}
@ -1485,8 +1486,8 @@ namespace Avalonia.Controls
// If the row has been recycled, reapply the BackgroundBrush
if (row.IsRecycled)
{
row.EnsureBackground();
row.ApplyCellsState();
_rowsPresenter?.InvalidateChildIndex(row);
}
else if (row == EditingRow)
{

5
src/Avalonia.Controls.DataGrid/DataGridTextColumn.cs

@ -19,8 +19,6 @@ namespace Avalonia.Controls
/// </summary>
public class DataGridTextColumn : DataGridBoundColumn
{
private const string DATAGRID_TextColumnCellTextBlockMarginKey = "DataGridTextColumnCellTextBlockMargin";
/// <summary>
/// Initializes a new instance of the <see cref="T:Avalonia.Controls.DataGridTextColumn" /> class.
/// </summary>
@ -178,8 +176,7 @@ namespace Avalonia.Controls
{
TextBlock textBlockElement = new TextBlock
{
[!Layoutable.MarginProperty] = new DynamicResourceExtension(DATAGRID_TextColumnCellTextBlockMarginKey),
VerticalAlignment = VerticalAlignment.Center
Name = "CellTextBlock"
};
SyncProperties(textBlockElement);

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

@ -3,12 +3,13 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using Avalonia.Controls;
using Avalonia.Controls.Utils;
namespace Avalonia.Controls.Primitives
{
@ -16,9 +17,10 @@ namespace Avalonia.Controls.Primitives
/// Used within the template of a <see cref="T:Avalonia.Controls.DataGrid" />
/// to specify the location in the control's visual tree where the cells are to be added.
/// </summary>
public sealed class DataGridCellsPresenter : Panel
public sealed class DataGridCellsPresenter : Panel, IChildIndexProvider
{
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
@ -42,6 +44,25 @@ namespace Avalonia.Controls.Primitives
set;
}
event EventHandler<ChildIndexChangedEventArgs> IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
}
int IChildIndexProvider.GetChildIndex(ILogical child)
{
return child is DataGridCell cell
? OwningGrid.ColumnsInternal.GetColumnDisplayIndex(cell.ColumnIndex)
: throw new InvalidOperationException("Invalid cell type");
}
bool IChildIndexProvider.TryGetTotalCount(out int count)
{
count = OwningGrid.ColumnsInternal.VisibleColumnCount;
return true;
}
/// <summary>
/// Arranges the content of the <see cref="T:Avalonia.Controls.Primitives.DataGridCellsPresenter" />.
/// </summary>
@ -120,6 +141,13 @@ namespace Avalonia.Controls.Primitives
}
}
protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
{
base.ChildrenChanged(sender, e);
InvalidateChildIndex();
}
private static void EnsureCellDisplay(DataGridCell cell, bool displayColumn)
{
if (cell.IsCurrent)
@ -304,6 +332,11 @@ namespace Avalonia.Controls.Primitives
DesiredHeight = 0;
}
internal void InvalidateChildIndex()
{
_childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
}
private bool ShouldDisplayCell(DataGridColumn column, double frozenLeftEdge, double scrollingLeftEdge)
{
if (!column.IsVisible)

36
src/Avalonia.Controls.DataGrid/Primitives/DataGridColumnHeadersPresenter.cs

@ -3,8 +3,10 @@
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
using Avalonia.LogicalTree;
using Avalonia.Media;
using System;
using System.Collections.Specialized;
using System.Diagnostics;
namespace Avalonia.Controls.Primitives
@ -13,10 +15,11 @@ namespace Avalonia.Controls.Primitives
/// Used within the template of a <see cref="T:Avalonia.Controls.DataGrid" /> to specify the
/// location in the control's visual tree where the column headers are to be added.
/// </summary>
public sealed class DataGridColumnHeadersPresenter : Panel
public sealed class DataGridColumnHeadersPresenter : Panel, IChildIndexProvider
{
private Control _dragIndicator;
private IControl _dropLocationIndicator;
private EventHandler<ChildIndexChangedEventArgs> _childIndexChanged;
/// <summary>
/// Tracks which column is currently being dragged.
@ -104,6 +107,25 @@ namespace Avalonia.Controls.Primitives
set;
}
event EventHandler<ChildIndexChangedEventArgs> IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
}
int IChildIndexProvider.GetChildIndex(ILogical child)
{
return child is DataGridColumnHeader header
? OwningGrid.ColumnsInternal.GetColumnDisplayIndex(header.ColumnIndex)
: throw new InvalidOperationException("Invalid cell type");
}
bool IChildIndexProvider.TryGetTotalCount(out int count)
{
count = OwningGrid.ColumnsInternal.VisibleColumnCount;
return true;
}
/// <summary>
/// Arranges the content of the <see cref="T:Avalonia.Controls.Primitives.DataGridColumnHeadersPresenter" />.
/// </summary>
@ -391,5 +413,17 @@ namespace Avalonia.Controls.Primitives
OwningGrid.ColumnsInternal.EnsureVisibleEdgedColumnsWidth();
return new Size(OwningGrid.ColumnsInternal.VisibleEdgedColumnsWidth, height);
}
protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e)
{
base.ChildrenChanged(sender, e);
InvalidateChildIndex();
}
internal void InvalidateChildIndex()
{
_childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
}
}
}

29
src/Avalonia.Controls.DataGrid/Primitives/DataGridRowsPresenter.cs

@ -7,8 +7,8 @@ using System;
using System.Diagnostics;
using Avalonia.Input;
using Avalonia.Input.GestureRecognizers;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Media;
namespace Avalonia.Controls.Primitives
@ -17,8 +17,10 @@ namespace Avalonia.Controls.Primitives
/// Used within the template of a <see cref="T:Avalonia.Controls.DataGrid" /> to specify the
/// location in the control's visual tree where the rows are to be added.
/// </summary>
public sealed class DataGridRowsPresenter : Panel
public sealed class DataGridRowsPresenter : Panel, IChildIndexProvider
{
private EventHandler<ChildIndexChangedEventArgs> _childIndexChanged;
public DataGridRowsPresenter()
{
AddHandler(Gestures.ScrollGestureEvent, OnScrollGesture);
@ -44,6 +46,29 @@ namespace Avalonia.Controls.Primitives
}
}
event EventHandler<ChildIndexChangedEventArgs> IChildIndexProvider.ChildIndexChanged
{
add => _childIndexChanged += value;
remove => _childIndexChanged -= value;
}
int IChildIndexProvider.GetChildIndex(ILogical child)
{
return child is DataGridRow row
? row.Index
: throw new InvalidOperationException("Invalid DataGrid child");
}
bool IChildIndexProvider.TryGetTotalCount(out int count)
{
return OwningGrid.DataConnection.TryGetCount(false, true, out count);
}
internal void InvalidateChildIndex(DataGridRow row)
{
_childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs(row));
}
/// <summary>
/// Arranges the content of the <see cref="T:Avalonia.Controls.Primitives.DataGridRowsPresenter" />.
/// </summary>

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

@ -12,23 +12,32 @@
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<ControlTemplate>
<Grid ColumnDefinitions="*,Auto"
Background="{TemplateBinding Background}">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
TextElement.Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle Name="PART_RightGridLine"
Grid.Column="1"
VerticalAlignment="Stretch"
Width="1" />
</Grid>
<Border x:Name="CellBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid ColumnDefinitions="*,Auto">
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle Name="PART_RightGridLine"
Grid.Column="1"
VerticalAlignment="Stretch"
Width="1" />
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="DataGridCell > TextBlock#CellTextBlock">
<Setter Property="Margin" Value="{DynamicResource DataGridTextColumnCellTextBlockMargin}" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style Selector="DataGridColumnHeader">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
@ -40,35 +49,40 @@
<Setter Property="Template">
<ControlTemplate>
<Grid ColumnDefinitions="*,Auto"
Background="{TemplateBinding Background}">
<Grid ColumnDefinitions="*,Auto"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}">
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Path Name="SortIcon"
Grid.Column="1"
Fill="{TemplateBinding Foreground}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Stretch="Uniform"
Width="8"
Margin="4,0,0,0"
Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z "/>
<Border x:Name="HeaderBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid ColumnDefinitions="*,Auto">
<Grid ColumnDefinitions="*,Auto"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}">
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Path Name="SortIcon"
Grid.Column="1"
Fill="{TemplateBinding Foreground}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Stretch="Uniform"
Width="8"
Margin="4,0,0,0"
Data="F1 M -5.215,6.099L 5.215,6.099L 0,0L -5.215,6.099 Z "/>
</Grid>
</Grid>
<Rectangle Name="VerticalSeparator"
Grid.Column="1" Width="1"
VerticalAlignment="Stretch"
Fill="{TemplateBinding SeparatorBrush}"
IsVisible="{TemplateBinding AreSeparatorsVisible}" />
<Rectangle Name="VerticalSeparator"
Grid.Column="1" Width="1"
VerticalAlignment="Stretch"
Fill="{TemplateBinding SeparatorBrush}"
IsVisible="{TemplateBinding AreSeparatorsVisible}" />
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
@ -102,22 +116,35 @@
<Style Selector="DataGridRow">
<Setter Property="Template">
<ControlTemplate>
<DataGridFrozenGrid Name="PART_Root"
RowDefinitions="*,Auto,Auto"
ColumnDefinitions="Auto,*">
<Border x:Name="RowBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<DataGridFrozenGrid Name="PART_Root"
RowDefinitions="*,Auto,Auto"
ColumnDefinitions="Auto,*">
<Rectangle Name="BackgroundRectangle" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
<Rectangle Name="BackgroundRectangle" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
<DataGridRowHeader Grid.RowSpan="3" Name="PART_RowHeader" DataGridFrozenGrid.IsFrozen="True" />
<DataGridCellsPresenter Grid.Column="1" Name="PART_CellsPresenter" DataGridFrozenGrid.IsFrozen="True" />
<DataGridDetailsPresenter Grid.Row="1" Grid.Column="1" Name="PART_DetailsPresenter"/>
<Rectangle Grid.Row="2" Grid.Column="1" Name="PART_BottomGridLine" HorizontalAlignment="Stretch" Height="1" />
<DataGridRowHeader Grid.RowSpan="3" Name="PART_RowHeader" DataGridFrozenGrid.IsFrozen="True" />
<DataGridCellsPresenter Grid.Column="1" Name="PART_CellsPresenter" DataGridFrozenGrid.IsFrozen="True" />
<DataGridDetailsPresenter Grid.Row="1" Grid.Column="1" Name="PART_DetailsPresenter"/>
<Rectangle Grid.Row="2" Grid.Column="1" Name="PART_BottomGridLine" HorizontalAlignment="Stretch" Height="1" />
</DataGridFrozenGrid>
</DataGridFrozenGrid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="DataGridRow">
<Setter Property="Background" Value="{Binding $parent[DataGrid].RowBackground}" />
</Style>
<Style Selector="DataGridRow:nth-child(even)">
<Setter Property="Background" Value="{Binding $parent[DataGrid].AlternatingRowBackground}" />
</Style>
<Style Selector="DataGridRow /template/ Rectangle#BackgroundRectangle">
<Setter Property="IsVisible" Value="False"/>
<Setter Property="Fill" Value="{DynamicResource HighlightBrush}" />
@ -180,12 +207,18 @@
<Setter Property="Template">
<ControlTemplate>
<DataGridFrozenGrid Name="Root"
Background="{TemplateBinding Background}"
ColumnDefinitions="Auto,Auto,Auto,Auto"
RowDefinitions="Auto,*,Auto">
ColumnDefinitions="Auto,Auto,Auto,Auto"
RowDefinitions="Auto,*,Auto">
<Rectangle Grid.Column="1" Grid.Row="1" Name="IndentSpacer" />
<ToggleButton Grid.Column="2" Grid.Row="1" Name="ExpanderButton" Margin="2,0,0,0"/>
<ToggleButton Grid.Column="2" Grid.Row="1"
Name="ExpanderButton"
Margin="2,0,0,0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="{TemplateBinding CornerRadius}"
Foreground="{TemplateBinding Foreground}" />
<StackPanel Grid.Column="3" Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" Margin="0,1,0,1">
<TextBlock Name="PropertyNameElement" Margin="4,0,0,0" IsVisible="{TemplateBinding IsPropertyNameVisible}"/>
@ -238,9 +271,11 @@
</Setter>
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
<Border x:Name="DataGridBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
CornerRadius="{TemplateBinding CornerRadius}">
<Grid RowDefinitions="Auto,*,Auto,Auto" ColumnDefinitions="Auto,*,Auto">
<DataGridColumnHeader Name="PART_TopLeftCornerHeader" Width="22" />

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

@ -93,58 +93,66 @@
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<ControlTemplate>
<Grid x:Name="PART_CellRoot"
ColumnDefinitions="*,Auto"
Background="{TemplateBinding Background}">
<Border x:Name="CellBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid x:Name="PART_CellRoot" ColumnDefinitions="*,Auto">
<Rectangle x:Name="CurrencyVisual"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCurrencyVisualPrimaryBrush}"
StrokeThickness="1" />
<Grid x:Name="FocusVisual"
IsHitTestVisible="False">
<Rectangle HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualPrimaryBrush}"
StrokeThickness="2" />
<Rectangle Margin="2"
<Rectangle x:Name="CurrencyVisual"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualSecondaryBrush}"
Stroke="{DynamicResource DataGridCurrencyVisualPrimaryBrush}"
StrokeThickness="1" />
</Grid>
<Grid x:Name="FocusVisual" IsHitTestVisible="False">
<Rectangle HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualPrimaryBrush}"
StrokeThickness="2" />
<Rectangle Margin="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualSecondaryBrush}"
StrokeThickness="1" />
</Grid>
<ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Margin="{TemplateBinding Padding}"
TextElement.Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<ContentPresenter Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Foreground="{TemplateBinding Foreground}" />
<Rectangle x:Name="InvalidVisualElement"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellInvalidBrush}"
StrokeThickness="1" />
<Rectangle x:Name="InvalidVisualElement"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellInvalidBrush}"
StrokeThickness="1" />
<Rectangle Name="PART_RightGridLine"
Grid.Column="1"
VerticalAlignment="Stretch"
Width="1"
Fill="{DynamicResource DataGridFillerColumnGridLinesBrush}" />
</Grid>
<Rectangle Name="PART_RightGridLine"
Grid.Column="1"
Width="1"
VerticalAlignment="Stretch"
Fill="{DynamicResource DataGridFillerColumnGridLinesBrush}" />
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="DataGridCell > TextBlock#CellTextBlock">
<Setter Property="Margin" Value="{DynamicResource DataGridTextColumnCellTextBlockMargin}" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style Selector="DataGridCell /template/ Rectangle#CurrencyVisual">
<Setter Property="IsVisible" Value="False" />
</Style>
@ -180,57 +188,58 @@
<Setter Property="MinHeight" Value="32" />
<Setter Property="Template">
<ControlTemplate>
<Grid Name="PART_ColumnHeaderRoot"
ColumnDefinitions="*,Auto"
Background="{TemplateBinding Background}">
<Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition MinWidth="32"
Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Path Name="SortIcon"
Grid.Column="1"
Fill="{TemplateBinding Foreground}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
Height="12" />
</Grid>
<Rectangle Name="VerticalSeparator"
Grid.Column="1"
Width="1"
VerticalAlignment="Stretch"
Fill="{TemplateBinding SeparatorBrush}"
IsVisible="{TemplateBinding AreSeparatorsVisible}" />
<Border x:Name="HeaderBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid Name="PART_ColumnHeaderRoot" ColumnDefinitions="*,Auto">
<Grid Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" MinWidth="32" />
</Grid.ColumnDefinitions>
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" />
<Path Name="SortIcon"
Grid.Column="1"
Height="12"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{TemplateBinding Foreground}"
Stretch="Uniform" />
</Grid>
<Grid x:Name="FocusVisual"
IsHitTestVisible="False">
<Rectangle x:Name="FocusVisualPrimary"
HorizontalAlignment="Stretch"
<Rectangle Name="VerticalSeparator"
Grid.Column="1"
Width="1"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualPrimaryBrush}"
StrokeThickness="2" />
<Rectangle x:Name="FocusVisualSecondary"
Margin="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualSecondaryBrush}"
StrokeThickness="1" />
Fill="{TemplateBinding SeparatorBrush}"
IsVisible="{TemplateBinding AreSeparatorsVisible}" />
<Grid x:Name="FocusVisual" IsHitTestVisible="False">
<Rectangle x:Name="FocusVisualPrimary"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualPrimaryBrush}"
StrokeThickness="2" />
<Rectangle x:Name="FocusVisualSecondary"
Margin="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="Transparent"
IsHitTestVisible="False"
Stroke="{DynamicResource DataGridCellFocusVisualSecondaryBrush}"
StrokeThickness="1" />
</Grid>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
@ -271,38 +280,51 @@
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<ControlTemplate>
<DataGridFrozenGrid Name="PART_Root"
RowDefinitions="*,Auto,Auto"
ColumnDefinitions="Auto,*">
<Rectangle Name="BackgroundRectangle"
Grid.RowSpan="2"
Grid.ColumnSpan="2" />
<Rectangle x:Name="InvalidVisualElement"
Grid.ColumnSpan="2"
Fill="{DynamicResource DataGridRowInvalidBrush}" />
<DataGridRowHeader Name="PART_RowHeader"
Grid.RowSpan="3"
DataGridFrozenGrid.IsFrozen="True" />
<DataGridCellsPresenter Name="PART_CellsPresenter"
Grid.Column="1"
DataGridFrozenGrid.IsFrozen="True" />
<DataGridDetailsPresenter Name="PART_DetailsPresenter"
Grid.Row="1"
<Border x:Name="RowBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<DataGridFrozenGrid Name="PART_Root"
ColumnDefinitions="Auto,*"
RowDefinitions="*,Auto,Auto">
<Rectangle Name="BackgroundRectangle"
Grid.RowSpan="2"
Grid.ColumnSpan="2" />
<Rectangle x:Name="InvalidVisualElement"
Grid.ColumnSpan="2"
Fill="{DynamicResource DataGridRowInvalidBrush}" />
<DataGridRowHeader Name="PART_RowHeader"
Grid.RowSpan="3"
DataGridFrozenGrid.IsFrozen="True" />
<DataGridCellsPresenter Name="PART_CellsPresenter"
Grid.Column="1"
Background="{DynamicResource DataGridDetailsPresenterBackgroundBrush}" />
<Rectangle Name="PART_BottomGridLine"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Stretch"
Height="1" />
DataGridFrozenGrid.IsFrozen="True" />
<DataGridDetailsPresenter Name="PART_DetailsPresenter"
Grid.Row="1"
Grid.Column="1"
Background="{DynamicResource DataGridDetailsPresenterBackgroundBrush}" />
<Rectangle Name="PART_BottomGridLine"
Grid.Row="2"
Grid.Column="1"
Height="1"
HorizontalAlignment="Stretch" />
</DataGridFrozenGrid>
</DataGridFrozenGrid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="DataGridRow">
<Setter Property="Background" Value="{Binding $parent[DataGrid].RowBackground}" />
</Style>
<Style Selector="DataGridRow:nth-child(even)">
<Setter Property="Background" Value="{Binding $parent[DataGrid].AlternatingRowBackground}" />
</Style>
<Style Selector="DataGridRow /template/ Rectangle#InvalidVisualElement">
<Setter Property="Opacity" Value="0" />
</Style>
@ -430,9 +452,12 @@
Width="12"
Height="12"
Margin="12,0,0,0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Focusable="False" />
CornerRadius="{TemplateBinding CornerRadius}"
Focusable="False"
Foreground="{TemplateBinding Foreground}" />
<StackPanel Grid.Column="3"
Orientation="Horizontal"
@ -559,11 +584,12 @@
</Setter>
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
<Border x:Name="DataGridBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid RowDefinitions="Auto,*,Auto,Auto"
ColumnDefinitions="Auto,*,Auto">
CornerRadius="{TemplateBinding CornerRadius}">
<Grid ColumnDefinitions="Auto,*,Auto" RowDefinitions="Auto,*,Auto,Auto">
<Grid.Resources>
<ControlTemplate x:Key="TopLeftHeaderTemplate"
TargetType="DataGridColumnHeader">

5
src/Avalonia.Controls/Calendar/DateTimeHelper.cs

@ -68,10 +68,7 @@ namespace Avalonia.Controls
public static DateTime DiscardDayTime(DateTime d)
{
int year = d.Year;
int month = d.Month;
DateTime newD = new DateTime(year, month, 1, 0, 0, 0);
return newD;
return new DateTime(d.Year, d.Month, 1, 0, 0, 0);
}
[return: NotNullIfNotNull("d")]

2
src/Avalonia.Controls/ItemsControl.cs

@ -166,7 +166,7 @@ namespace Avalonia.Controls
if (Presenter is IChildIndexProvider innerProvider)
{
innerProvider.ChildIndexChanged += PresenterChildIndexChanged;
_childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs());
_childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
}
}

2
src/Avalonia.Controls/Panel.cs

@ -147,7 +147,7 @@ namespace Avalonia.Controls
throw new NotSupportedException();
}
_childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs());
_childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
InvalidateMeasureOnChildrenChanged();
}

2
src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs

@ -158,7 +158,7 @@ namespace Avalonia.Controls.Presenters
{
ItemsChanged(e);
_childIndexChanged?.Invoke(this, new ChildIndexChangedEventArgs());
_childIndexChanged?.Invoke(this, ChildIndexChangedEventArgs.Empty);
}
}

Loading…
Cancel
Save