Browse Source

Clear DataContext of cleared elements in ItemsRepeater

When we set the DataContext, we save that fact in the VirtualizationInformation for that element, when that element gets cleared, we look up in the VirtualizationInformation whether we should need to clear the DataContext too, and do that if necessary.

Ported from e9bd88e598
pull/4091/head
Steven Kirk 6 years ago
parent
commit
7c69f3ee00
  1. 24
      src/Avalonia.Controls/Repeater/ViewManager.cs
  2. 1
      src/Avalonia.Controls/Repeater/VirtualizationInfo.cs

24
src/Avalonia.Controls/Repeater/ViewManager.cs

@ -110,10 +110,28 @@ namespace Avalonia.Controls
}
}
// We need to clear the datacontext to prevent crashes from happening,
// however we only do that if we were the ones setting it.
// That is when one of the following is the case (numbering taken from line ~642):
// 1.2 No ItemTemplate, data is not a UIElement
// 2.1 ItemTemplate, data is not FrameworkElement
// 2.2.2 Itemtemplate, data is FrameworkElement, ElementFactory returned Element different to data
//
// In all of those three cases, we the ItemTemplateShim is NOT null.
// Luckily when we create the items, we store whether we were the once setting the DataContext.
public void ClearElementToElementFactory(IControl element)
{
_owner.OnElementClearing(element);
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
virtInfo.MoveOwnershipToElementFactory();
// During creation of this object, we were the one setting the DataContext, so clear it now.
if (virtInfo.MustClearDataContext)
{
element.DataContext = null;
}
if (_owner.ItemTemplateShim != null)
{
_owner.ItemTemplateShim.RecycleElement(_owner, element);
@ -127,9 +145,6 @@ namespace Avalonia.Controls
}
}
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element);
virtInfo.MoveOwnershipToElementFactory();
if (_lastFocusedElement == element)
{
// Focused element is going away. Remove the tracked last focused element
@ -597,11 +612,14 @@ namespace Avalonia.Controls
{
virtInfo = ItemsRepeater.CreateAndInitializeVirtualizationInfo(element);
}
// Clear flag
virtInfo.MustClearDataContext = false;
if (data != element)
{
// Prepare the element
element.DataContext = data;
virtInfo.MustClearDataContext = true;
}
virtInfo.MoveOwnershipToLayoutFromElementFactory(

1
src/Avalonia.Controls/Repeater/VirtualizationInfo.cs

@ -36,6 +36,7 @@ namespace Avalonia.Controls
public bool IsHeldByLayout => Owner == ElementOwner.Layout;
public bool IsRealized => IsHeldByLayout || Owner == ElementOwner.PinnedPool;
public bool IsInUniqueIdResetPool => Owner == ElementOwner.UniqueIdResetPool;
public bool MustClearDataContext { get; set; }
public bool KeepAlive { get; set; }
public ElementOwner Owner { get; private set; } = ElementOwner.ElementFactory;
public string UniqueId { get; private set; }

Loading…
Cancel
Save