diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000000..80716520d9
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,31 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. Windows, Mac, Linux (State distribution)]
+ - Version [e.g. 0.10.0-rc1 or 0.9.12]
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000..bbcbbe7d61
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 15392278c9..fbd8507193 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -51,7 +51,7 @@ jobs:
inputs:
actions: 'build'
scheme: ''
- sdk: 'macosx11.0'
+ sdk: 'macosx11.1'
configuration: 'Release'
xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
xcodeVersion: '12' # Options: 8, 9, default, specifyPath
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 43ec995ed9..9a268a21e7 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -21,6 +21,6 @@
-
+
diff --git a/native/Avalonia.Native/src/OSX/rendertarget.mm b/native/Avalonia.Native/src/OSX/rendertarget.mm
index 00b6dab219..b2d4341bb9 100644
--- a/native/Avalonia.Native/src/OSX/rendertarget.mm
+++ b/native/Avalonia.Native/src/OSX/rendertarget.mm
@@ -111,7 +111,11 @@
if(_renderbuffer != 0)
glDeleteRenderbuffers(1, &_renderbuffer);
}
- CFRelease(surface);
+
+ if(surface != nullptr)
+ {
+ CFRelease(surface);
+ }
}
@end
@@ -145,6 +149,12 @@ static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* ta
}
- (void)resize:(AvnPixelSize)size withScale: (float) scale{
+
+ if(size.Height <= 0)
+ size.Height = 1;
+ if(size.Width <= 0)
+ size.Width = 1;
+
@synchronized (lock) {
if(surface == nil
|| surface->size.Width != size.Width
diff --git a/readme.md b/readme.md
index b5cb38df90..cfa08149cb 100644
--- a/readme.md
+++ b/readme.md
@@ -10,6 +10,8 @@ Avalonia is a cross-platform XAML-based UI framework providing a flexible stylin
+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
+
> **Note:** The UI theme you see in the picture above is still work-in-progress and will be available in the upcoming Avalonia 0.10.0 release. However, you can connect to our nightly build feed and install latest pre-release versions of Avalonia NuGet packages, if you are willing to help out with the development and testing. See [Using nightly build feed](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed) for more info.
To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
@@ -31,11 +33,16 @@ Install-Package Avalonia.Desktop
Examples of UIs built with Avalonia

+([Synfonia](https://github.com/jmacato/Synfonia))
+

+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))

+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))

+([Xaml Control Gallery](https://github.com/AvaloniaUI/xamlcontrolsgallery))
## JetBrains Rider
diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs
index e582153f41..8f9b9583cf 100644
--- a/src/Avalonia.Controls.DataGrid/DataGrid.cs
+++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs
@@ -1,6 +1,6 @@
// 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.
+// All other rights reserved.
using Avalonia.Collections;
using Avalonia.Controls.Primitives;
@@ -92,7 +92,7 @@ namespace Avalonia.Controls
private ContentControl _topRightCornerHeader;
private Control _frozenColumnScrollBarSpacer;
- // the sum of the widths in pixels of the scrolling columns preceding
+ // the sum of the widths in pixels of the scrolling columns preceding
// the first displayed scrolling column
private double _horizontalOffset;
@@ -143,7 +143,7 @@ namespace Avalonia.Controls
private object _uneditedValue; // Represents the original current cell value at the time it enters editing mode.
private ICellEditBinding _currentCellEditBinding;
- // An approximation of the sum of the heights in pixels of the scrolling rows preceding
+ // An approximation of the sum of the heights in pixels of the scrolling rows preceding
// the first displayed scrolling row. Since the scrolled off rows are discarded, the grid
// does not know their actual height. The heights used for the approximation are the ones
// set as the rows were scrolled off.
@@ -162,7 +162,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(CanUserReorderColumns));
///
- /// Gets or sets a value that indicates whether the user can change
+ /// Gets or sets a value that indicates whether the user can change
/// the column display order by dragging column headers with the mouse.
///
public bool CanUserReorderColumns
@@ -247,8 +247,8 @@ namespace Avalonia.Controls
/// Gets or sets the that is used to paint the background of odd-numbered rows.
///
///
- /// The brush that is used to paint the background of odd-numbered rows. The default is a
- /// with a
+ /// The brush that is used to paint the background of odd-numbered rows. The default is a
+ /// with a
/// value of white (ARGB value #00FFFFFF).
///
public IBrush AlternatingRowBackground
@@ -379,8 +379,8 @@ namespace Avalonia.Controls
public bool IsValid
{
get { return _isValid; }
- internal set
- {
+ internal set
+ {
SetAndRaise(IsValidProperty, ref _isValid, value);
PseudoClasses.Set(":invalid", !value);
}
@@ -398,7 +398,7 @@ namespace Avalonia.Controls
}
///
- /// Gets or sets the maximum width of columns in the .
+ /// Gets or sets the maximum width of columns in the .
///
public double MaxColumnWidth
{
@@ -418,7 +418,7 @@ namespace Avalonia.Controls
}
///
- /// Gets or sets the minimum width of columns in the .
+ /// Gets or sets the minimum width of columns in the .
///
public double MinColumnWidth
{
@@ -496,7 +496,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(VerticalGridLinesBrush));
///
- /// Gets or sets the that is used to paint grid lines separating columns.
+ /// Gets or sets the that is used to paint grid lines separating columns.
///
public IBrush VerticalGridLinesBrush
{
@@ -542,7 +542,7 @@ namespace Avalonia.Controls
///
///
/// The index of the current selection, or -1 if the selection is empty.
- ///
+ ///
public int SelectedIndex
{
get { return _selectedIndex; }
@@ -582,7 +582,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(AutoGenerateColumns));
///
- /// Gets or sets a value that indicates whether columns are created
+ /// Gets or sets a value that indicates whether columns are created
/// automatically when the property is set.
///
public bool AutoGenerateColumns
@@ -626,7 +626,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register(nameof(AreRowDetailsFrozen));
///
- /// Gets or sets a value that indicates whether the row details sections remain
+ /// Gets or sets a value that indicates whether the row details sections remain
/// fixed at the width of the display area or can scroll horizontally.
///
public bool AreRowDetailsFrozen
@@ -881,7 +881,7 @@ namespace Avalonia.Controls
{
int index = (int)e.NewValue;
- // GetDataItem returns null if index is >= Count, we do not check newValue
+ // GetDataItem returns null if index is >= Count, we do not check newValue
// against Count here to avoid enumerating through an Enumerable twice
// Setting SelectedItem coerces the finally value of the SelectedIndex
object newSelectedItem = (index < 0) ? null : DataConnection.GetDataItem(index);
@@ -1168,14 +1168,14 @@ namespace Avalonia.Controls
}
///
- /// Occurs one time for each public, non-static property in the bound data type when the
- /// property is changed and the
+ /// Occurs one time for each public, non-static property in the bound data type when the
+ /// property is changed and the
/// property is true.
///
public event EventHandler AutoGeneratingColumn;
///
- /// Occurs before a cell or row enters editing mode.
+ /// Occurs before a cell or row enters editing mode.
///
public event EventHandler BeginningEdit;
@@ -1195,7 +1195,7 @@ namespace Avalonia.Controls
public event EventHandler CellPointerPressed;
///
- /// Occurs when the
+ /// Occurs when the
/// property of a column changes.
///
public event EventHandler ColumnDisplayIndexChanged;
@@ -1218,14 +1218,14 @@ namespace Avalonia.Controls
public event EventHandler CurrentCellChanged;
///
- /// Occurs after a
+ /// Occurs after a
/// is instantiated, so that you can customize it before it is used.
///
public event EventHandler LoadingRow;
///
/// Occurs when a cell in a enters editing mode.
- ///
+ ///
///
public event EventHandler PreparingCellForEdit;
@@ -1243,7 +1243,7 @@ namespace Avalonia.Controls
RoutedEvent.Register(nameof(SelectionChanged), RoutingStrategies.Bubble);
///
- /// Occurs when the or
+ /// Occurs when the or
/// property value changes.
///
public event EventHandler SelectionChanged
@@ -1258,19 +1258,19 @@ namespace Avalonia.Controls
public event EventHandler Sorting;
///
- /// Occurs when a
+ /// Occurs when a
/// object becomes available for reuse.
///
public event EventHandler UnloadingRow;
///
- /// Occurs when a new row details template is applied to a row, so that you can customize
+ /// Occurs when a new row details template is applied to a row, so that you can customize
/// the details section before it is used.
///
public event EventHandler LoadingRowDetails;
///
- /// Occurs when the
+ /// Occurs when the
/// property value changes.
///
public event EventHandler RowDetailsVisibilityChanged;
@@ -1282,7 +1282,7 @@ namespace Avalonia.Controls
///
/// Gets a collection that contains all the columns in the control.
- ///
+ ///
public ObservableCollection Columns
{
get
@@ -1456,7 +1456,7 @@ namespace Avalonia.Controls
}
// Height currently available for cells this value is smaller. This height is reduced by the existence of ColumnHeaders
- // or a horizontal scrollbar. Layout is asynchronous so changes to the ColumnHeaders or the horizontal scrollbar are
+ // or a horizontal scrollbar. Layout is asynchronous so changes to the ColumnHeaders or the horizontal scrollbar are
// not reflected immediately.
internal double CellsHeight
{
@@ -1555,7 +1555,7 @@ namespace Avalonia.Controls
internal static double HorizontalGridLinesThickness => DATAGRID_horizontalGridLinesThickness;
- // the sum of the widths in pixels of the scrolling columns preceding
+ // the sum of the widths in pixels of the scrolling columns preceding
// the first displayed scrolling column
internal double HorizontalOffset
{
@@ -2083,20 +2083,20 @@ namespace Avalonia.Controls
}
///
- /// Measures the children of a to prepare for
- /// arranging them during the
- /// pass.
+ /// Measures the children of a to prepare for
+ /// arranging them during the
+ /// pass.
///
///
/// The size that the determines it needs during layout, based on its calculations of child object allocated sizes.
///
///
- /// The available size that this element can give to child elements. Indicates an upper limit that
+ /// The available size that this element can give to child elements. Indicates an upper limit that
/// child elements should not exceed.
///
protected override Size MeasureOverride(Size availableSize)
{
- // Delay layout until after the initial measure to avoid invalid calculations when the
+ // Delay layout until after the initial measure to avoid invalid calculations when the
// DataGrid is not part of the visual tree
if (!_measured)
{
@@ -3020,7 +3020,7 @@ namespace Avalonia.Controls
/// If the editing element has focus, this method will set focus to the DataGrid itself
/// in order to force the element to lose focus. It will then wait for the editing element's
/// LostFocus event, at which point it will perform the specified action.
- ///
+ ///
/// NOTE: It is important to understand that the specified action will be performed when the editing
/// element loses focus only if this method returns true. If it returns false, then the action
/// will not be performed later on, and should instead be performed by the caller, if necessary.
@@ -3079,7 +3079,7 @@ namespace Avalonia.Controls
{
if (!_scrollingByHeight)
{
- // Update layout when RowDetails are expanded or collapsed, just updating the vertical scroll bar is not enough
+ // Update layout when RowDetails are expanded or collapsed, just updating the vertical scroll bar is not enough
// since rows could be added or removed
InvalidateMeasure();
}
@@ -3292,7 +3292,7 @@ namespace Avalonia.Controls
{
// Current cell was reset because the commit deleted row(s).
// Since the user wants to change the current cell, we don't
- // want to end up with no current cell. We pick the last row
+ // want to end up with no current cell. We pick the last row
// in the grid which may be the 'new row'.
int lastSlot = LastVisibleSlot;
if (forCurrentCellChange &&
@@ -3350,7 +3350,7 @@ namespace Avalonia.Controls
if (_ignoreNextScrollBarsLayout)
{
_ignoreNextScrollBarsLayout = false;
- //
+ //
}
@@ -3407,7 +3407,7 @@ namespace Avalonia.Controls
}
// Now cellsWidth is the width potentially available for displaying data cells.
- // Now cellsHeight is the height potentially available for displaying data cells.
+ // Now cellsHeight is the height potentially available for displaying data cells.
bool needHorizScrollbar = false;
bool needVertScrollbar = false;
@@ -3432,7 +3432,7 @@ namespace Avalonia.Controls
Debug.Assert(cellsHeight >= 0);
needHorizScrollbarWithoutVertScrollbar = needHorizScrollbar = true;
- if (vertScrollBarWidth > 0 &&
+ if (vertScrollBarWidth > 0 &&
allowVertScrollbar && (MathUtilities.LessThanOrClose(totalVisibleWidth - cellsWidth, vertScrollBarWidth) ||
MathUtilities.LessThanOrClose(cellsWidth - totalVisibleFrozenWidth, vertScrollBarWidth)))
{
@@ -3472,7 +3472,7 @@ namespace Avalonia.Controls
// we compute the number of visible columns only after we set up the vertical scroll bar.
ComputeDisplayedColumns();
- if ((vertScrollBarWidth > 0 || horizScrollBarHeight > 0) &&
+ if ((vertScrollBarWidth > 0 || horizScrollBarHeight > 0) &&
allowHorizScrollbar &&
needVertScrollbar && !needHorizScrollbar &&
MathUtilities.GreaterThan(totalVisibleWidth, cellsWidth) &&
@@ -3977,7 +3977,8 @@ namespace Avalonia.Controls
{
var errorList =
binding.ValidationErrors
- .SelectMany(ex => ValidationUtil.UnpackException(ex))
+ .SelectMany(ValidationUtil.UnpackException)
+ .Select(ValidationUtil.UnpackDataValidationException)
.ToList();
DataValidationErrors.SetErrors(editingElement, errorList);
@@ -4138,7 +4139,7 @@ namespace Avalonia.Controls
}
///
- /// Exits editing mode without trying to commit or revert the editing, and
+ /// Exits editing mode without trying to commit or revert the editing, and
/// without repopulating the edited row's cell.
///
//TODO TabStop
@@ -5117,9 +5118,9 @@ namespace Avalonia.Controls
{
if (ctrl || _editingColumnIndex == -1 || IsReadOnly)
{
- //Go to the next/previous control on the page when
+ //Go to the next/previous control on the page when
// - Ctrl key is used
- // - Potential current cell is not edited, or the datagrid is read-only.
+ // - Potential current cell is not edited, or the datagrid is read-only.
return false;
}
@@ -5530,11 +5531,11 @@ namespace Avalonia.Controls
// v---v
//|<|_____|###|>|
// ^ ^
- // min max
+ // min max
// we want to make the relative size of the thumb reflect the relative size of the viewing area
// viewportSize / (max + viewportSize) = cellsWidth / max
- // -> viewportSize = max * cellsWidth / (max - cellsWidth)
+ // -> viewportSize = max * cellsWidth / (max - cellsWidth)
// always zero
_hScrollBar.Minimum = 0;
@@ -5586,7 +5587,7 @@ namespace Avalonia.Controls
_hScrollBar.Maximum = 0;
if (_hScrollBar.IsVisible)
{
- // This will trigger a call to this method via Cells_SizeChanged for
+ // This will trigger a call to this method via Cells_SizeChanged for
// which no processing is needed.
_hScrollBar.IsVisible = false;
_ignoreNextScrollBarsLayout = true;
@@ -5605,14 +5606,14 @@ namespace Avalonia.Controls
// v---v
//|<|_____|###|>|
// ^ ^
- // min max
+ // min max
// we want to make the relative size of the thumb reflect the relative size of the viewing area
// viewportSize / (max + viewportSize) = cellsWidth / max
// -> viewportSize = max * cellsHeight / (totalVisibleHeight - cellsHeight)
// -> = max * cellsHeight / (totalVisibleHeight - cellsHeight)
// -> = max * cellsHeight / max
- // -> = cellsHeight
+ // -> = cellsHeight
// always zero
_vScrollBar.Minimum = 0;
@@ -5635,7 +5636,7 @@ namespace Avalonia.Controls
if (!_vScrollBar.IsVisible)
{
- // This will trigger a call to this method via Cells_SizeChanged for
+ // This will trigger a call to this method via Cells_SizeChanged for
// which no processing is needed.
_vScrollBar.IsVisible = true;
if (_vScrollBar.DesiredSize.Width == 0)
@@ -5651,7 +5652,7 @@ namespace Avalonia.Controls
_vScrollBar.Maximum = 0;
if (_vScrollBar.IsVisible)
{
- // This will trigger a call to this method via Cells_SizeChanged for
+ // This will trigger a call to this method via Cells_SizeChanged for
// which no processing is needed.
_vScrollBar.IsVisible = false;
_ignoreNextScrollBarsLayout = true;
@@ -5674,8 +5675,8 @@ namespace Avalonia.Controls
Debug.Assert(slot >= 0);
// Before changing selection, check if the current cell needs to be committed, and
- // check if the current row needs to be committed. If any of those two operations are required and fail,
- // do not change selection, and do not change current cell.
+ // check if the current row needs to be committed. If any of those two operations are required and fail,
+ // do not change selection, and do not change current cell.
bool wasInEdit = EditingColumnIndex != -1;
diff --git a/src/Avalonia.Controls.DataGrid/Utils/ValidationUtil.cs b/src/Avalonia.Controls.DataGrid/Utils/ValidationUtil.cs
index e1ecb2c562..c36d9708c1 100644
--- a/src/Avalonia.Controls.DataGrid/Utils/ValidationUtil.cs
+++ b/src/Avalonia.Controls.DataGrid/Utils/ValidationUtil.cs
@@ -80,19 +80,24 @@ namespace Avalonia.Controls.Utils
{
if (exception != null)
{
- var aggregate = exception as AggregateException;
- var exceptions = aggregate == null ?
- (IEnumerable)new[] { exception } :
- aggregate.InnerExceptions;
- var filtered = exceptions.Where(x => !(x is BindingChainException)).ToList();
+ var exceptions = exception is AggregateException aggregate ?
+ aggregate.InnerExceptions :
+ (IEnumerable)new[] { exception };
- if (filtered.Count > 0)
- {
- return filtered;
- }
+ return exceptions.Where(x => !(x is BindingChainException)).ToList();
}
- return null;
+ return Array.Empty();
+ }
+
+ public static object UnpackDataValidationException(Exception exception)
+ {
+ if (exception is DataValidationException dataValidationException)
+ {
+ return dataValidationException.ErrorData;
+ }
+
+ return exception;
}
///
diff --git a/src/Avalonia.Controls/ContextMenu.cs b/src/Avalonia.Controls/ContextMenu.cs
index 5e17182f3e..fb8080f0d4 100644
--- a/src/Avalonia.Controls/ContextMenu.cs
+++ b/src/Avalonia.Controls/ContextMenu.cs
@@ -246,7 +246,7 @@ namespace Avalonia.Controls
///
/// Opens the menu.
///
- public override void Open() => throw new NotSupportedException();
+ public override void Open() => Open(null);
///
/// Opens a context menu on the specified control.
diff --git a/src/Avalonia.Layout/ElementManager.cs b/src/Avalonia.Layout/ElementManager.cs
index 70805ba31c..bf5a45966b 100644
--- a/src/Avalonia.Layout/ElementManager.cs
+++ b/src/Avalonia.Layout/ElementManager.cs
@@ -129,7 +129,7 @@ namespace Avalonia.Layout
{
for (int i = 0; i < count; i++)
{
- // Clear from the edges so that ItemsRepeater can optimize on maintaining
+ // Clear from the edges so that ItemsRepeater can optimize on maintaining
// realized indices without walking through all the children every time.
int index = realizedIndex == 0 ? realizedIndex + i : (realizedIndex + count - 1) - i;
var elementRef = _realizedElements[index];
@@ -212,7 +212,7 @@ namespace Avalonia.Layout
public ILayoutable GetRealizedElement(int dataIndex)
{
return IsVirtualizingContext ?
- GetAt(GetRealizedRangeIndexFromDataIndex(dataIndex)) :
+ GetAt(GetRealizedRangeIndexFromDataIndex(dataIndex)) :
_context.GetOrCreateElementAt(
dataIndex,
ElementRealizationOptions.ForceCreate | ElementRealizationOptions.SuppressAutoRecycle);
@@ -252,7 +252,6 @@ namespace Avalonia.Layout
(orientation == ScrollOrientation.Vertical ? ScrollOrientation.Horizontal : ScrollOrientation.Vertical) :
orientation;
-
var windowStart = effectiveOrientation == ScrollOrientation.Vertical ? window.Y : window.X;
var windowEnd = effectiveOrientation == ScrollOrientation.Vertical ? window.Y + window.Height : window.X + window.Width;
var firstElementStart = effectiveOrientation == ScrollOrientation.Vertical ? firstElementBounds.Y : firstElementBounds.X;
@@ -273,53 +272,53 @@ namespace Avalonia.Layout
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
- {
- OnItemsAdded(args.NewStartingIndex, args.NewItems.Count);
- }
- break;
+ {
+ OnItemsAdded(args.NewStartingIndex, args.NewItems.Count);
+ }
+ break;
case NotifyCollectionChangedAction.Replace:
- {
- int oldSize = args.OldItems.Count;
- int newSize = args.NewItems.Count;
- int oldStartIndex = args.OldStartingIndex;
- int newStartIndex = args.NewStartingIndex;
-
- if (oldSize == newSize &&
- oldStartIndex == newStartIndex &&
- IsDataIndexRealized(oldStartIndex) &&
- IsDataIndexRealized(oldStartIndex + oldSize -1))
{
- // Straight up replace of n items within the realization window.
- // Removing and adding might causes us to lose the anchor causing us
- // to throw away all containers and start from scratch.
- // Instead, we can just clear those items and set the element to
- // null (sentinel) and let the next measure get new containers for them.
- var startRealizedIndex = GetRealizedRangeIndexFromDataIndex(oldStartIndex);
- for (int realizedIndex = startRealizedIndex; realizedIndex < startRealizedIndex + oldSize; realizedIndex++)
+ int oldSize = args.OldItems.Count;
+ int newSize = args.NewItems.Count;
+ int oldStartIndex = args.OldStartingIndex;
+ int newStartIndex = args.NewStartingIndex;
+
+ if (oldSize == newSize &&
+ oldStartIndex == newStartIndex &&
+ IsDataIndexRealized(oldStartIndex) &&
+ IsDataIndexRealized(oldStartIndex + oldSize - 1))
{
- var elementRef = _realizedElements[realizedIndex];
-
- if (elementRef != null)
+ // Straight up replace of n items within the realization window.
+ // Removing and adding might causes us to lose the anchor causing us
+ // to throw away all containers and start from scratch.
+ // Instead, we can just clear those items and set the element to
+ // null (sentinel) and let the next measure get new containers for them.
+ var startRealizedIndex = GetRealizedRangeIndexFromDataIndex(oldStartIndex);
+ for (int realizedIndex = startRealizedIndex; realizedIndex < startRealizedIndex + oldSize; realizedIndex++)
{
- _context.RecycleElement(elementRef);
- _realizedElements[realizedIndex] = null;
+ var elementRef = _realizedElements[realizedIndex];
+
+ if (elementRef != null)
+ {
+ _context.RecycleElement(elementRef);
+ _realizedElements[realizedIndex] = null;
+ }
}
}
+ else
+ {
+ OnItemsRemoved(oldStartIndex, oldSize);
+ OnItemsAdded(newStartIndex, newSize);
+ }
}
- else
- {
- OnItemsRemoved(oldStartIndex, oldSize);
- OnItemsAdded(newStartIndex, newSize);
- }
- }
- break;
+ break;
case NotifyCollectionChangedAction.Remove:
- {
- OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count);
- }
- break;
+ {
+ OnItemsRemoved(args.OldStartingIndex, args.OldItems.Count);
+ }
+ break;
case NotifyCollectionChangedAction.Reset:
ClearRealizedRange();
@@ -376,7 +375,7 @@ namespace Avalonia.Layout
int backCutoffIndex = realizedRangeSize;
for (int i = 0;
- i _firstRealizedDataIndex &&
+ if (newStartingIndex >= _firstRealizedDataIndex &&
newStartingIndex <= lastRealizedDataIndex)
{
// Inserted within the realized range
int insertRangeStartIndex = newStartingIndex - _firstRealizedDataIndex;
for (int i = 0; i < count; i++)
{
- // Insert null (sentinel) here instead of an element, that way we dont
+ // Insert null (sentinel) here instead of an element, that way we dont
// end up creating a lot of elements only to be thrown out in the next layout.
int insertRangeIndex = insertRangeStartIndex + i;
int dataIndex = newStartingIndex + i;
diff --git a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml
index 97ca62c493..ad0fd18ea5 100644
--- a/src/Avalonia.Themes.Fluent/Controls/Expander.xaml
+++ b/src/Avalonia.Themes.Fluent/Controls/Expander.xaml
@@ -108,7 +108,7 @@